Add android-mock to external

Android mock is used by QuickSearchBox to mock classes instead of
creating tons of interfaces.

Change-Id: Ib53ca3a6c5e8e27f42b66cc9e39bbf0d55ed2170
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..6734347
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,41 @@
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_SDK_VERSION := 8
+LOCAL_STATIC_JAVA_LIBRARIES := easymocklib
+LOCAL_MODULE := android-mock-runtimelib
+LOCAL_MOCKING_PATH := src/com/google/android/testing/mocking/
+LOCAL_SRC_FILES := \
+      $(LOCAL_MOCKING_PATH)/AndroidMock.java \
+      $(LOCAL_MOCKING_PATH)/SdkVersion.java \
+      $(LOCAL_MOCKING_PATH)/FileUtils.java \
+      $(LOCAL_MOCKING_PATH)/GeneratedClassFile.java \
+      $(LOCAL_MOCKING_PATH)/MockObject.java \
+      $(LOCAL_MOCKING_PATH)/UsesMocks.java
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE_TAGS := tests
+LOCAL_MODULE := android-mock-generatorlib
+LOCAL_SRC_FILES := $(call all-java-files-under, src)
+LOCAL_STATIC_JAVA_LIBRARIES := easymock javassist
+
+include $(BUILD_HOST_JAVA_LIBRARY)
diff --git a/HOWTO.txt b/HOWTO.txt
new file mode 100644
index 0000000..3821d83
--- /dev/null
+++ b/HOWTO.txt
@@ -0,0 +1 @@
+This is a copy from the android mock project, http://code.google.com/p/android-mock/. To regenerate, use the regenerate_from_source.sh; full instructions about this script are there.
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..75b5248
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,202 @@
+

+                                 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

+

+   APPENDIX: How to apply the Apache License to your work.

+

+      To apply the Apache License to your work, attach the following

+      boilerplate notice, with the fields enclosed by brackets "[]"

+      replaced with your own identifying information. (Don't include

+      the brackets!)  The text should be enclosed in the appropriate

+      comment syntax for the file format. We also recommend that a

+      file or class name and description of purpose be included on the

+      same "printed page" as the copyright notice for easier

+      identification within third-party archives.

+

+   Copyright [yyyy] [name of copyright owner]

+

+   Licensed under the Apache License, Version 2.0 (the "License");

+   you may not use this file except in compliance with the License.

+   You may obtain a copy of the License at

+

+       http://www.apache.org/licenses/LICENSE-2.0

+

+   Unless required by applicable law or agreed to in writing, software

+   distributed under the License is distributed on an "AS IS" BASIS,

+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+   See the License for the specific language governing permissions and

+   limitations under the License.

diff --git a/build.properties b/build.properties
new file mode 100644
index 0000000..2e10482
--- /dev/null
+++ b/build.properties
@@ -0,0 +1,8 @@
+easymock-jar=easymock.jar
+framework.mock-bin=bin
+framework.mock-jar=android_framework_mocks.jar
+java-package=com/google/android/testing/mocking
+javassist-jar=javassist.jar
+lib-folder=lib
+source-base=src
+staging=staging
diff --git a/build.xml b/build.xml
new file mode 100644
index 0000000..bad7e25
--- /dev/null
+++ b/build.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="Android Mock" default="all-tests" basedir=".">
+  <description>
+Android Mock is a wrapper for EasyMock (2.4) which allows for real Class mocking on
+an Android (Dalvik) VM.
+
+All methods on Android Mock are syntactically equivalent to EasyMock method
+calls, and will delegate calls to EasyMock, while performing the required
+transformations to avoid Dalvik VM troubles.
+
+Calls directly to EasyMock will work correctly only if the Class being mocked
+is in fact an Interface. Calls to Android Mock will work correctly for both
+Interfaces and concrete Classes.
+
+Android Mock requires that the code being mocked be instrumented prior to
+loading to the Dalvik VM by having called the MockGenerator.jar file. Try
+running java -jar MockGenerator.jar --help for more information.
+  </description>
+
+  <!-- Global Build Properties -->
+  <property file="build.properties"/>
+
+  <!-- Imports -->
+  <import file="src/build-runtime.xml"/>
+  <import file="src/build-mockgen.xml"/>
+  <import file="src/build-framework-gen.xml"/>
+
+  <!-- Android Mock Source Jar Properties -->
+  <property name="source-bin" value="bin/source"/>
+  <property name="source-lib-jar" value="AndroidMock-src.jar"/>
+
+  <!-- Android Mock Test Properties -->
+  <property name="junit-jar" value="junit.jar"/>
+  <property name="test-bin" value="bin/tests"/>
+  <property name="test-results-folder" value="${test-bin}/results"/>
+  <property name="test-source-base" value="tests"/>
+
+  <!-- Classpaths -->
+  <path id="tests.path">
+    <pathelement location="${lib-folder}/${easymock-jar}"/>
+    <pathelement location="${lib-folder}/${javassist-jar}"/>
+    <pathelement location="${runtime.bin}/${runtime.deploy-jar}"/>
+    <pathelement location="${mockgen.bin}/${mockgen.deploy-jar}"/>
+    <pathelement location="${lib-folder}/${junit-jar}"/>
+  </path>
+
+  <!-- Private Build Targets -->
+  <target name="-dirs">
+    <mkdir dir="${source-bin}"/>
+    <mkdir dir="${test-bin}"/>
+    <mkdir dir="${staging}"/>
+    <mkdir dir="${test-results-folder}"/>
+  </target>
+
+  <target name="-clean-staging">
+    <delete dir="${staging}"/>
+  </target>
+
+  <!-- Public Build Targets -->
+  <target name="clean" depends="-clean-staging,mockgen.clean,runtime.clean">
+    <delete dir="${source-bin}"/>
+    <delete dir="${framework-mock-staging}"/>
+    <delete dir="${test-results-folder}" failonerror="false"/>
+    <delete dir="${test-bin}" failonerror="false"/>
+  </target>
+
+  <target name="build-dist"
+      depends="mockgen.build-deploy, runtime.build-deploy, build-source-lib"/>
+
+  <target name="build-source-lib" depends="-dirs"
+      description="Builds a jar file containing the Android Mock source files (no dependencies)">
+    <jar destfile="${source-bin}/${source-lib-jar}" basedir="${source-base}" includes="**/*.java"/>
+  </target>
+
+  <!-- Public Test Targets -->
+  <target name="all-tests" depends="-test-base"
+      description="Builds the full distribution package and runs all tests storing results in ${test-results-folder}">
+    <junit printsummary="no" showoutput="no" reloading="false" failureproperty="testsFailed">
+      <formatter type="xml"/>
+      <classpath location="${test-bin}"/>
+      <classpath refid="tests.path"/>
+      <batchtest todir="${test-results-folder}">
+        <fileset dir="${test-bin}">
+          <include name="**/*Test.class"/>
+          <include name="**/*Tests.class"/>
+        </fileset>
+      </batchtest>
+    </junit>
+    <echo>Test Results are available in ${test-results-folder}</echo>
+    <junitreport todir="${test-results-folder}">
+      <fileset dir="${test-results-folder}">
+        <include name="TEST-*.xml"/>
+      </fileset>
+      <report format="frames" todir="${test-results-folder}/html"/>
+    </junitreport>
+    <fail if="testsFailed" message="Tests failed"/>
+  </target>
+
+  <!-- Private Test Targets -->
+  <target name="-test-base" depends="build-dist">
+    <javac destdir="${test-bin}" target="1.5" srcdir="${test-source-base}"
+        debug="true" >
+      <compilerarg value="-proc:none"/>
+      <classpath refid="tests.path"/>
+    </javac>
+  </target>
+
+</project>
diff --git a/livetests/com/google/android/testing/mocking/test/AndroidManifest.xml b/livetests/com/google/android/testing/mocking/test/AndroidManifest.xml
new file mode 100644
index 0000000..a35c31e
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/test/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<!--
+/*
+ * Copyright 2010 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.
+ */
+-->
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.google.android.testing.mocking.test"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <application android:label="@string/app_name">
+        <uses-library android:name="android.test.runner" />
+    </application>
+    <uses-sdk android:minSdkVersion="3"/>
+    <instrumentation android:targetPackage="com.google.android.testing.mocking.test"
+                     android:name="android.test.InstrumentationTestRunner" />
+</manifest>
+
diff --git a/livetests/com/google/android/testing/mocking/test/MockingTest.java b/livetests/com/google/android/testing/mocking/test/MockingTest.java
new file mode 100644
index 0000000..ee527a9
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/test/MockingTest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking.test;
+
+import android.content.Context;
+
+import com.google.android.testing.mocking.AndroidMock;
+import com.google.android.testing.mocking.SdkVersion;
+import com.google.android.testing.mocking.UsesMocks;
+import com.google.android.testing.mocking.testapp.ClassToMock;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests that Android Mock provides correct mocks when running on a Dalvik VM.
+ * 
+ * @author swoodward (Stephen Woodward)
+ */
+public class MockingTest extends TestCase {
+  /**
+   * Test that an SDK class is mocked correctly, that is to say the mock
+   * comes from the pre-generated set, and it corresponds to the correct
+   * runtime environment
+   */
+  @UsesMocks(Context.class)
+  public void testFrameworkMock() {
+    Context mockContext = AndroidMock.createMock(Context.class);
+    String packageName = mockContext.getClass().getPackage().getName();
+    assertEquals(SdkVersion.getCurrentVersion().getPackagePrefix(),
+        packageName.substring(0, packageName.indexOf('.') + 1));
+  }
+
+  /**
+   * Test that a non-SDK class is mocked correctly
+   */
+  @UsesMocks(ClassToMock.class)
+  public void testNormalMock() {
+    ClassToMock myMockClass = AndroidMock.createMock(ClassToMock.class);
+    AndroidMock.expect(myMockClass.getString()).andReturn(
+        "I'm the king of the world, king of the -- d'oh!");
+    AndroidMock.expect(myMockClass.getInt()).andReturn(42);
+    AndroidMock.replay(myMockClass);
+    assertEquals("I'm the king of the world, king of the -- d'oh!",
+        myMockClass.getString());
+    assertEquals(42, myMockClass.getInt());
+    AndroidMock.verify(myMockClass);
+  }
+}
+
diff --git a/livetests/com/google/android/testing/mocking/test/res/layout/main.xml b/livetests/com/google/android/testing/mocking/test/res/layout/main.xml
new file mode 100644
index 0000000..c1fe411
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/test/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:text="@string/hello"
+    />
+</LinearLayout>
+
diff --git a/livetests/com/google/android/testing/mocking/test/res/values/strings.xml b/livetests/com/google/android/testing/mocking/test/res/values/strings.xml
new file mode 100644
index 0000000..224fc4a
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/test/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="hello">Hello World!</string>
+    <string name="app_name">AndroidMockTestAppTest</string>
+</resources>
diff --git a/livetests/com/google/android/testing/mocking/testapp/AndroidManifest.xml b/livetests/com/google/android/testing/mocking/testapp/AndroidManifest.xml
new file mode 100644
index 0000000..02fdb20
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/testapp/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<!--
+/*
+ * Copyright 2010 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.
+ */
+-->
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.google.android.testing.mocking.testapp"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <application android:label="@string/app_name">
+        <activity android:name=".TestAppActivity"
+                  android:label="@string/app_name">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+    <uses-sdk android:minSdkVersion="3" />
+</manifest> 
diff --git a/livetests/com/google/android/testing/mocking/testapp/ClassToMock.java b/livetests/com/google/android/testing/mocking/testapp/ClassToMock.java
new file mode 100644
index 0000000..8c51220
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/testapp/ClassToMock.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking.testapp;
+
+/**
+ * Dummy class to be mocked.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassToMock {
+  public String getString() {
+    return "foo";
+  }
+
+  public int getInt() {
+    return -1;
+  }
+}
diff --git a/livetests/com/google/android/testing/mocking/testapp/TestAppActivity.java b/livetests/com/google/android/testing/mocking/testapp/TestAppActivity.java
new file mode 100644
index 0000000..c1d6756
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/testapp/TestAppActivity.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking.testapp;
+
+import com.google.android.testing.mocking.testapp.R;
+import com.google.android.testing.mocking.testapp.R.layout;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Extremely simple Activity to give our Mocking Test something to test.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class TestAppActivity extends Activity {
+    /** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.main);
+    }
+}
diff --git a/livetests/com/google/android/testing/mocking/testapp/res/layout/main.xml b/livetests/com/google/android/testing/mocking/testapp/res/layout/main.xml
new file mode 100644
index 0000000..c1fe411
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/testapp/res/layout/main.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:text="@string/hello"
+    />
+</LinearLayout>
+
diff --git a/livetests/com/google/android/testing/mocking/testapp/res/values/strings.xml b/livetests/com/google/android/testing/mocking/testapp/res/values/strings.xml
new file mode 100644
index 0000000..e53d336
--- /dev/null
+++ b/livetests/com/google/android/testing/mocking/testapp/res/values/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="hello">Hello World, TestAppActivity!</string>
+    <string name="app_name">AndroidMockTestApp</string>
+</resources>
diff --git a/regenerate_from_source.sh b/regenerate_from_source.sh
new file mode 100644
index 0000000..0dacd87
--- /dev/null
+++ b/regenerate_from_source.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+#
+# Copyright (C) 2011 The Android Open Source Project.
+# This script imports the src, test, etc. from android-mock It DOESN'T commit
+# to git giving you a chance to review the changes. Remember that changes in
+# bin are normally ignored by git, but we need to force them this case.
+# This script doesn't take any parameter.
+
+svn export --force http://android-mock.googlecode.com/svn/trunk/ .
+rm lib/easymock.jar
+rm lib/junit.jar
+rm lib/javassist.jar
+rm lib/android/*
+# I don't check if there is something on lib on purpose; that way, if
+# anything new is added, we will get a visible error.
+rmdir lib/android
+rmdir lib
diff --git a/src/build-framework-gen.xml b/src/build-framework-gen.xml
new file mode 100644
index 0000000..c23ba7e
--- /dev/null
+++ b/src/build-framework-gen.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="AndroidMockGenerator" default="frameworkgen.build" basedir="..">
+  <!-- Global Properties -->
+  <property file="../build.properties"/>
+
+  <!-- Imports -->
+  <import file="build-mockgen.xml"/>
+
+  <!-- Android Framework Mockgen Properties -->
+  <property name="android-lib-folder" value="${lib-folder}/android"/>
+  <property name="framework.mock-staging" value="staging/android_framework_mocks"/>
+  <property name="android-15-jar" value="android_v15.jar"/>
+  <property name="android-16-jar" value="android_v16.jar"/>
+  <property name="android-201-jar" value="android_v201.jar"/>
+  <property name="android-21-jar" value="android_v21.jar"/>
+  <property name="android-22-jar" value="android_v22.jar"/>
+
+  <!-- property name="framework.mock-bin" value=see build.properties -->
+  <!-- property name="framework.mock-jar" value=see build.properties -->
+
+  <!-- Private Targets -->
+  <target name="-frameworkgen.dirs">
+    <mkdir dir="${framework.mock-bin}"/>
+    <mkdir dir="${framework.mock-staging}"/>
+  </target>
+
+  <target name="-frameworkgen.clean-staging">
+    <delete dir="${staging}"/>
+  </target>
+
+  <!-- Public Targets -->
+  <target name="frameworkgen.clean" depends="-frameworkgen.clean-staging">
+    <delete dir="${framework.mock-bin}/${framework.mock-jar}"/>
+    <delete dir="${framework.mock-staging}"/>
+  </target>
+
+  <target name="frameworkgen.build"
+      depends="-frameworkgen.clean-staging,-frameworkgen.dirs,mockgen.build-deploy"
+      description="Builds the mock support files for mocking Android Framework classes.">
+
+    <generate-framework-mocks api-jar-file="${android-15-jar}" api-level="3"/>
+    <generate-framework-mocks api-jar-file="${android-16-jar}" api-level="4"/>
+    <generate-framework-mocks api-jar-file="${android-201-jar}" api-level="6"/>
+    <generate-framework-mocks api-jar-file="${android-21-jar}" api-level="7"/>
+    <generate-framework-mocks api-jar-file="${android-22-jar}" api-level="8"/>
+    <jar destfile="${framework.mock-bin}/${framework.mock-jar}"
+         basedir="${framework.mock-staging}" includes="**/*.class" index="true"/>
+  </target>
+
+  <!-- Macros -->
+  <macrodef name="generate-framework-mocks">
+    <attribute name="api-jar-file"/>
+    <attribute name="api-level"/>
+    <sequential>
+      <java classname="com.google.android.testing.mocking.AndroidFrameworkMockGenerator" fork="true">
+        <classpath>
+          <pathelement location="${mockgen.bin}/${mockgen.deploy-jar}"/>
+          <pathelement location="${android-lib-folder}/@{api-jar-file}"/>
+        </classpath>
+        <arg value="${framework.mock-staging}"/>
+        <arg value="@{api-level}"/>
+      </java>
+    </sequential>
+  </macrodef>
+
+</project>
\ No newline at end of file
diff --git a/src/build-mockgen.xml b/src/build-mockgen.xml
new file mode 100644
index 0000000..3a9a9c4
--- /dev/null
+++ b/src/build-mockgen.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="AndroidMockGenerator" default="mockgen.build" basedir="..">
+  <!-- Global Properties -->
+  <property file="../build.properties"/>
+
+  <!-- Android Mock Generator Properties -->
+  <property name="mockgen.bin" value="bin"/>
+  <property name="mockgen.class-bin" value="bin/classes"/>
+  <property name="mockgen.deploy-jar" value="AndroidMockGenerator.jar"/>
+  <property name="mockgen.includes" value="${java-package}/GeneratedMockJar.readme"/>
+  <property name="mockgen.java-files" value="com/google/android/testing/mocking/*.java"/>
+  <property name="mockgen.nodeps-jar" value="AndroidMockGenerator-nodeps.jar"/>
+  <property name="meta-service-folder" value="META-INF/services"/>
+  <property name="annotations-meta-file"
+      value="${meta-service-folder}/javax.annotation.processing.Processor"/>
+
+  <!-- Classpaths -->
+  <path id="generator.path">
+    <pathelement location="${lib-folder}/${easymock-jar}"/>
+    <pathelement location="${lib-folder}/${javassist-jar}"/>
+  </path>
+
+  <!--  Private Targets -->
+  <target name="-mockgen.dirs">
+    <mkdir dir="${mockgen.bin}"/>
+    <mkdir dir="${mockgen.class-bin}"/>
+    <mkdir dir="${mockgen.class-bin}/${meta-service-folder}"/>
+  </target>
+
+  <target name="-mockgen.clean-staging">
+    <delete dir="${staging}"/>
+  </target>
+
+  <!--  Public Targets -->
+  <target name="mockgen.clean" depends="-mockgen.clean-staging">
+    <delete file="${mockgen.deploy-jar}"/>
+    <delete file="${mockgen.nodeps-jar}"/>
+    <delete dir="${mockgen.class-bin}"/>
+  </target>
+
+  <target name="mockgen.build" depends="-mockgen.clean-staging,-mockgen.dirs"
+      description="Builds the Mock Generator jar file">
+    <javac destdir="${mockgen.class-bin}" srcdir="${source-base}"
+           includes="${mockgen.java-files}" debug="true">
+      <classpath refid="generator.path"/>
+    </javac>
+    <copy todir="${mockgen.class-bin}">
+      <fileset dir="${source-base}" includes="${mockgen.includes}"/>
+    </copy>
+    <echo file="${mockgen.class-bin}/${annotations-meta-file}"
+        message="com.google.android.testing.mocking.UsesMocksProcessor"/>
+    <manifestclasspath property="frameworkjar.classpath"
+                       jarfile="${mockgen.bin}/${mockgen.nodeps-jar}">
+      <classpath location="${framework.mock-bin}/${framework.mock-jar}"/>
+    </manifestclasspath>
+    <tstamp>
+      <format property="build.time" pattern="dd-MMMM-yyyy hh:mm aa"/>
+    </tstamp>
+    <jar destfile="${mockgen.bin}/${mockgen.nodeps-jar}" basedir="${mockgen.class-bin}">
+      <manifest>
+        <attribute name="Built-On" value="${build.time}"/>
+      </manifest>
+    </jar>
+  </target>
+
+  <target name="mockgen.build-deploy" depends="mockgen.build"
+      description="Builds the Mock Generator jar file with dependencies included.">
+    <unjar dest="${staging}">
+      <fileset dir=".">
+        <include name="${mockgen.bin}/${mockgen.nodeps-jar}"/>
+        <include name="${lib-folder}/${easymock-jar}"/>
+        <include name="${lib-folder}/${javassist-jar}"/>
+      </fileset>
+    </unjar>
+    <tstamp/>
+    <jar destfile="${mockgen.bin}/${mockgen.deploy-jar}" basedir="${staging}">
+      <manifest>
+        <attribute name="Built-On" value="${build.time}"/>
+      </manifest>
+    </jar>
+  </target>
+</project>
\ No newline at end of file
diff --git a/src/build-runtime.xml b/src/build-runtime.xml
new file mode 100644
index 0000000..5516985
--- /dev/null
+++ b/src/build-runtime.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project name="AndroidMockRuntime" default="runtime.build" basedir="..">
+  <!-- Global Properties -->
+  <property file="../build.properties"/>
+
+  <!-- Android Mock Runtime Properties -->
+  <property name="runtime.bin" value="bin"/>
+  <property name="runtime.class-bin" value="bin/classes"/>
+  <property name="runtime.deploy-jar" value="AndroidMockRuntime.jar"/>
+  <property name="runtime.java-files" value="${java-package}/AndroidMock.java 
+    ${java-package}/MockObject.java ${java-package}/UsesMocks.java"/>
+  <property name="runtime.nodeps-jar" value="AndroidMockRuntime-nodeps.jar"/>
+
+  <!-- Classpaths -->
+  <path id="path">
+    <pathelement location="${lib-folder}/${easymock-jar}"/>
+  </path>
+
+  <!-- Private Build Targets -->
+  <target name="-runtime.dirs">
+    <mkdir dir="${runtime.bin}"/>
+    <mkdir dir="${runtime.class-bin}"/>
+  </target>
+
+  <target name="-runtime.clean-staging">
+    <delete dir="${staging}"/>
+  </target>
+
+  <!-- Public Build Targets -->
+  <target name="runtime.clean" depends="-runtime.clean-staging">
+    <delete file="${runtime.deploy-jar}"/>
+    <delete file="${runtime.nodeps-jar}"/>
+    <delete dir="${runtime.class-bin}"/>
+  </target>
+
+  <target name="runtime.build" depends="-runtime.clean-staging,-runtime.dirs"
+      description="Builds the Android Mock Runtime library jar file without dependencies included.">
+    <javac destdir="${runtime.class-bin}" target="1.5" srcdir="${source-base}"
+        includes="${runtime.java-files}" debug="true">
+      <classpath refid="path"/>
+    </javac>
+    <jar destfile="${runtime.bin}/${runtime.nodeps-jar}" basedir="${runtime.class-bin}"/>
+  </target>
+
+  <target name="runtime.build-deploy" depends="runtime.build"
+      description="Builds the Android Mock Runtime library jar file with dependencies included.">
+    <unjar dest="${staging}">
+      <fileset dir=".">
+        <include name="${runtime.bin}/${runtime.nodeps-jar}"/>
+        <include name="${lib-folder}/${easymock-jar}"/>
+      </fileset>
+    </unjar>
+    <jar destfile="${runtime.bin}/${runtime.deploy-jar}" basedir="${staging}"/>
+  </target>
+</project>
\ No newline at end of file
diff --git a/src/com/google/android/testing/mocking/AndroidFrameworkMockGenerator.java b/src/com/google/android/testing/mocking/AndroidFrameworkMockGenerator.java
new file mode 100644
index 0000000..d634c24
--- /dev/null
+++ b/src/com/google/android/testing/mocking/AndroidFrameworkMockGenerator.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.NotFoundException;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * Mock Generator for Android Framework classes.
+ * 
+ * <p>
+ * This class will pull pre-defined mocks for Android framework classes. This is
+ * needed because a project might build against version X and then run against
+ * version Y, where the specification of the class being mocked will have
+ * changed, rendering the mock invalid.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class AndroidFrameworkMockGenerator {
+  private static final String LIB_FOLDER = "lib";
+  private static final String JAR_NAME = "android_";
+
+  /**
+   * Returns a set of mock support classes for the specified Class for all versions of
+   * the Android SDK. If the requested class is not part of the Android framework, then the class
+   * will not be found and an exception will be thrown.
+   * 
+   * @param clazz the class to mock.
+   * @return All available mock support classes (for all known Android SDKs) for
+   *         the requested Class.
+   */
+  public List<GeneratedClassFile> getMocksForClass(Class<?> clazz) throws ClassNotFoundException,
+      IOException {
+    List<Class<?>> prebuiltClasses = getPrebuiltClassesFor(clazz);
+    List<GeneratedClassFile> classList = new ArrayList<GeneratedClassFile>();
+    for (Class<?> prebuiltClass : prebuiltClasses) {
+      try {
+        CtClass ctClass = AndroidMockGenerator.getClassPool().get(prebuiltClass.getName());
+        classList.add(new GeneratedClassFile(ctClass.getName(), ctClass.toBytecode()));
+      } catch (NotFoundException e) {
+        throw new ClassNotFoundException("Missing class while fetching prebuilt mocks: "
+            + prebuiltClass.getName(), e);
+      } catch (CannotCompileException e) {
+        throw new RuntimeException("Internal Error copying a prebuilt mock: "
+            + prebuiltClass.getName(), e);
+      }
+    }
+    return classList;
+  }
+
+  private List<Class<?>> getPrebuiltClassesFor(Class<?> clazz) throws ClassNotFoundException {
+    List<Class<?>> classes = new ArrayList<Class<?>>();
+    SdkVersion[] versions = SdkVersion.getAllVersions();
+    for (SdkVersion sdkVersion : versions) {
+      classes.add(Class.forName(FileUtils.getSubclassNameFor(clazz, sdkVersion)));
+      classes.add(Class.forName(FileUtils.getInterfaceNameFor(clazz, sdkVersion)));
+    }
+    return classes;
+  }
+
+  /**
+   * @return a List of {@link GeneratedClassFile} objects representing the mocks for the specified
+   *         class for a single version of the Android SDK.
+   */
+  public List<GeneratedClassFile> createMocksForClass(Class<?> clazz, SdkVersion version)
+      throws ClassNotFoundException, IOException, CannotCompileException {
+    AndroidMockGenerator mockGenerator = new AndroidMockGenerator();
+    List<GeneratedClassFile> mocks = new ArrayList<GeneratedClassFile>();
+    mocks.addAll(mockGenerator.createMocksForClass(clazz, version));
+    return mocks;
+  }
+
+  /**
+   * @return A list of all class files inside the provided jar file.
+   */
+  List<Class<?>> getClassList(JarFile jar) throws ClassNotFoundException {
+    return getClassList(Collections.list(jar.entries()));
+  }
+
+  List<Class<?>> getClassList(Collection<JarEntry> jarEntries) throws ClassNotFoundException {
+    List<Class<?>> classList = new ArrayList<Class<?>>();
+    for (JarEntry jarEntry : jarEntries) {
+      if (jarEntryIsClassFile(jarEntry)) {
+        classList.add(Class.forName(FileUtils.getClassNameFor(jarEntry.getName())));
+      }
+    }
+    return classList;
+  }
+
+  /**
+   * @return true if the provided JarEntry represents a class file.
+   */
+  boolean jarEntryIsClassFile(JarEntry jarEntry) {
+    return jarEntry.getName().endsWith(".class");
+  }
+
+  /**
+   * @return the Android framework jar file for the specified {@link SdkVersion}.
+   */
+  static String getJarFileNameForVersion(SdkVersion version) {
+    return new StringBuilder()
+        .append(LIB_FOLDER)
+        .append(File.separator)
+        .append("android")
+        .append(File.separator)
+        .append(JAR_NAME)
+        .append(version.getVersionName())
+        .append(".jar").toString();
+  }
+
+  private static Set<GeneratedClassFile> generateMocks(
+      SdkVersion version, JarFile jar)
+      throws ClassNotFoundException, IOException, CannotCompileException {
+    AndroidFrameworkMockGenerator mockGenerator = new AndroidFrameworkMockGenerator();
+    List<Class<?>> classList = mockGenerator.getClassList(jar);
+    Set<GeneratedClassFile> classes = new HashSet<GeneratedClassFile>();
+    for (Class<?> clazz : classList) {
+      classes.addAll(mockGenerator.createMocksForClass(clazz, version));
+    }
+    return classes;
+  }
+
+  private static JarFile getJarFile(SdkVersion version) throws IOException {
+    File jarFile = new File(getJarFileNameForVersion(version)).getAbsoluteFile();
+    System.out.println("Using Jar File: " + jarFile.getAbsolutePath());
+    return new JarFile(jarFile);
+  }
+
+  public static void main(String[] args) {
+    try {
+      String outputFolderName = args[0];
+      SdkVersion version = SdkVersion.getVersionFor(Integer.parseInt(args[1]));
+      System.out.println("Generating files for " + version.getPackagePrefix());
+
+      JarFile jar = getJarFile(version);
+
+      Set<GeneratedClassFile> classes = generateMocks(version, jar);
+      for (GeneratedClassFile clazz : classes) {
+        FileUtils.saveClassToFolder(clazz, outputFolderName);
+      }
+    } catch (Exception e) {
+      throw new RuntimeException("Internal error generating framework mocks", e);
+    }
+  }
+}
diff --git a/src/com/google/android/testing/mocking/AndroidMock.java b/src/com/google/android/testing/mocking/AndroidMock.java
new file mode 100644
index 0000000..88f79b1
--- /dev/null
+++ b/src/com/google/android/testing/mocking/AndroidMock.java
@@ -0,0 +1,2804 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+import org.easymock.Capture;
+import org.easymock.EasyMock;
+import org.easymock.IArgumentMatcher;
+import org.easymock.IExpectationSetters;
+import org.easymock.LogicalOperator;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+
+/**
+ * Android Mock is a wrapper for EasyMock (2.4) which allows for real Class mocking on
+ * an Android (Dalvik) VM.
+ * 
+ * All methods on Android Mock are syntactically equivalent to EasyMock method
+ * calls, and will delegate calls to EasyMock, while performing the required
+ * transformations to avoid Dalvik VM troubles.
+ * 
+ * Calls directly to EasyMock will work correctly only if the Class being mocked
+ * is in fact an Interface. Calls to Android Mock will work correctly for both
+ * Interfaces and concrete Classes.
+ * 
+ * Android Mock requires that the code being mocked be instrumented prior to
+ * loading to the Dalvik VM by having called the MockGenerator.jar file. Try
+ * running {@code java -jar MockGenerator.jar --help} for more information.
+ * 
+ * An example usage pattern is:
+ * 
+ * {@code &#64;UsesMocks(MyClass.class) public void testFoo() &#123; MyClass
+ * mockObject = AndroidMock.createMock(MyClass.class);
+ * AndroidMock.expect(mockObject.foo(0)).andReturn(42);
+ * AndroidMock.replay(mockObject); assertEquals(42, mockObject.foo(0));
+ * AndroidMock.verify(mockObject); &#125; * }
+ * 
+ * 
+ * <b>A note about parameter and return types for the <i>expects</i> style of methods.</b>
+ * The various expectation methods such as {@link #eq(boolean)}, {@link #and(boolean, boolean)},
+ * and {@link #leq(byte)} all have nonsense return values. Each of the expectation methods may only
+ * be executed under strict conditions (in order to set expectations of incoming method parameters
+ * during record mode) and thus their return types are in fact never used. The return types are set
+ * only to satisfy the compile-time parameter requirements of the methods being mocked in order to
+ * allow code such as: {@code mockObject.doFoo(anyInt());}. If {@link #anyInt()} did not return
+ * {@code int} then the compiler would not accept the preceding code fragment.
+ * 
+ * Similarly, the complex expectation methods ({@code #and}, {@code #or}, and {@code not}) take
+ * various parameter types, but will throw an {@link java.lang.IllegalStateException} if anything
+ * other than an expectation method is provided.  E.g. {@code mockObject.doFoo(and(gt(5), lt(10));}
+ * 
+ * The benefit of this is to make it very easy to read the test code after it has been written.
+ * Additionally, the test code is protected by type safety at compile time.
+ * 
+ * The downside of this is that when writing the test code in the record phase, how to use the
+ * expectation APIs is not made clear by the method signatures of these expectation methods. In
+ * particular, it's not at all clear that {@link #and(byte, byte)} takes as parameters other
+ * expectation methods, and not just any random method that returns a {@literal byte} or even a
+ * {@literal byte} literal.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class AndroidMock {
+  private AndroidMock() {
+  }
+
+  /**
+   * Creates a mock object for the specified class, order checking
+   * is enabled by default. The difference between a strict mock and a normal mock is that a strict
+   * mock will not allow for invocations of the mock object to occur other than in the exact order
+   * specified during record mode.
+   * 
+   * The parameter {@literal args} allows the caller to choose which constructor on the Class
+   * specified by {@literal toMock} to be called when constructing the Mock object. If a constructor
+   * takes primitive values, Java Auto-boxing/unboxing will take care of it automatically, allowing
+   * the caller to make calls such as {@literal createStrictMock(MyObject.class, 42, "hello!")},
+   * where {@literal MyObject} defines a constructor such as
+   * {@literal public MyObject(int answer, String greeting)}.
+   * 
+   * @param <T> the class type to be mocked.
+   * @param toMock the class of the object to be mocked.
+   * @param args the arguments to pass to the constructor.
+   * @return the mock object.
+   */
+  public static <T> T createStrictMock(Class<T> toMock, Object... args) {
+    return createStrictMock(null, toMock, args);
+  }
+
+  /**
+   * Creates a mock object for the specified class, order checking
+   * is enabled by default. The difference between a strict mock and a normal mock is that a strict
+   * mock will not allow for invocations of the mock object to occur other than in the exact order
+   * specified during record mode.
+   * 
+   * The parameter {@literal args} allows the caller to choose which constructor on the Class
+   * specified by {@literal toMock} to be called when constructing the Mock object. If a constructor
+   * takes primitive values, Java Auto-boxing/unboxing will take care of it automatically, allowing
+   * the caller to make calls such as
+   * {@literal createStrictMock("NameMyMock", MyObject.class, 42, "hello!")},
+   * where {@literal MyObject} defines a constructor such as
+   * {@literal public MyObject(int answer, String greeting)}.
+   * 
+   * @param <T> the class type to be mocked.
+   * @param name the name of the mock object. This must be a valid Java identifier. This value is
+   * used as the return value from {@link #toString()} when invoked on the mock object.
+   * @param toMock the class of the object to be mocked.
+   * @param args the arguments to pass to the constructor.
+   * @return the mock object.
+   * @throws IllegalArgumentException if the name is not a valid Java identifier.
+   */
+  @SuppressWarnings("cast")
+  public static <T> T createStrictMock(String name, Class<T> toMock, Object... args) {
+    if (toMock.isInterface()) {
+      return EasyMock.createStrictMock(name, toMock);
+    }
+    Object mockedInterface = EasyMock.createStrictMock(name, getInterfaceFor(toMock));
+    return (T) getSubclassFor(toMock, getInterfaceFor(toMock), mockedInterface, args);
+  }
+
+  /**
+   * Creates a mock object for the specified class, order checking
+   * is disabled by default. A normal mock with order checking disabled will allow you to record
+   * the method invocations during record mode in any order. If order is important, use
+   * {@link #createStrictMock(Class, Object...)} instead.
+   * 
+   * The parameter {@literal args} allows the caller to choose which constructor on the Class
+   * specified by {@literal toMock} to be called when constructing the Mock object. If a constructor
+   * takes primitive values, Java Auto-boxing/unboxing will take care of it automatically, allowing
+   * the caller to make calls such as
+   * {@literal createMock(MyObject.class, 42, "hello!")},
+   * where {@literal MyObject} defines a constructor such as
+   * {@literal public MyObject(int answer, String greeting)}.
+   * 
+   * @param <T> the type of the class to be mocked.
+   * @param toMock the class object representing the class to be mocked.
+   * @param args the arguments to pass to the constructor.
+   * @return the mock object.
+   */
+  public static <T> T createMock(Class<T> toMock, Object... args) {
+    return createMock(null, toMock, args);
+  }
+
+  /**
+   * Creates a mock object for the specified class, order checking
+   * is disabled by default. A normal mock with order checking disabled will allow you to record
+   * the method invocations during record mode in any order. If order is important, use
+   * {@link #createStrictMock(Class, Object...)} instead.
+   * 
+   * The parameter {@literal args} allows the caller to choose which constructor on the Class
+   * specified by {@literal toMock} to be called when constructing the Mock object. If a constructor
+   * takes primitive values, Java Auto-boxing/unboxing will take care of it automatically, allowing
+   * the caller to make calls such as
+   * {@literal createMock("NameMyMock", MyObject.class, 42, "hello!")},
+   * where {@literal MyObject} defines a constructor such as
+   * {@literal public MyObject(int answer, String greeting)}.
+   * 
+   * @param <T> the type of the class to be mocked.
+   * @param name the name of the mock object. This must be a valid Java identifier. This value is
+   * used as the return value from {@link #toString()} when invoked on the mock object.
+   * @param toMock the class object representing the class to be mocked.
+   * @param args the arguments to pass to the constructor.
+   * @return the mock object.
+   * @throws IllegalArgumentException if the name is not a valid Java identifier.
+   */
+  @SuppressWarnings("cast")
+  public static <T> T createMock(String name, Class<T> toMock, Object... args) {
+    if (toMock.isInterface()) {
+      return EasyMock.createMock(name, toMock);
+    }
+    Object mockedInterface = EasyMock.createMock(name, getInterfaceFor(toMock));
+    return (T) getSubclassFor(toMock, getInterfaceFor(toMock), mockedInterface, args);
+  }
+
+  /**
+   * Creates a mock object for the specified class, order checking
+   * is disabled by default, and the mock object will return {@code 0},
+   * {@code null} or {@code false} for unexpected invocations.
+   * 
+   * The parameter {@literal args} allows the caller to choose which constructor on the Class
+   * specified by {@literal toMock} to be called when constructing the Mock object. If a constructor
+   * takes primitive values, Java Auto-boxing/unboxing will take care of it automatically, allowing
+   * the caller to make calls such as
+   * {@literal createNiceMock(MyObject.class, 42, "hello!")},
+   * where {@literal MyObject} defines a constructor such as
+   * {@literal public MyObject(int answer, String greeting)}.
+   * 
+   * @param <T> the type of the class to be mocked.
+   * @param toMock the class object representing the class to be mocked.
+   * @param args the arguments to pass to the constructor.
+   * @return the mock object.
+   */
+  public static <T> T createNiceMock(Class<T> toMock, Object... args) {
+    return createNiceMock(null, toMock, args);
+  }
+
+  /**
+   * Creates a mock object for the specified class, order checking
+   * is disabled by default, and the mock object will return {@code 0},
+   * {@code null} or {@code false} for unexpected invocations.
+   * 
+   * The parameter {@literal args} allows the caller to choose which constructor on the Class
+   * specified by {@literal toMock} to be called when constructing the Mock object. If a constructor
+   * takes primitive values, Java Auto-boxing/unboxing will take care of it automatically, allowing
+   * the caller to make calls such as
+   * {@literal createNiceMock("NameMyMock", MyObject.class, 42, "hello!")},
+   * where {@literal MyObject} defines a constructor such as
+   * {@literal public MyObject(int answer, String greeting)}.
+   * 
+   * @param <T> the type of the class to be mocked.
+   * @param name the name of the mock object. This must be a valid Java identifier. This value is
+   * used as the return value from {@link #toString()} when invoked on the mock object.
+   * @param toMock the class object representing the class to be mocked.
+   * @param args the arguments to pass to the constructor.
+   * @throws IllegalArgumentException if the name is not a valid Java identifier.
+   */
+  @SuppressWarnings("cast")
+  public static <T> T createNiceMock(String name, Class<T> toMock, Object... args) {
+    if (toMock.isInterface()) {
+      return EasyMock.createNiceMock(name, toMock);
+    }
+    Object mockedInterface = EasyMock.createNiceMock(name, getInterfaceFor(toMock));
+    return (T) getSubclassFor(toMock, getInterfaceFor(toMock), mockedInterface, args);
+  }
+
+  /**
+   * Returns the expectation setter for the last expected invocation in the current thread.
+   * Expectation setters are used during the recording phase to specify what method calls
+   * will be expected during the replay phase, and with which parameters. Parameters may be
+   * specified as literal values (e.g. {@code expect(mock.foo(42));  expect(mock.foo("hello"));})
+   * or according to parameter expectation criteria. Some examples of parameter expectation
+   * criteria include {@link #anyObject()}, {@link #leq(int)}, {@link #contains(String)},
+   * {@link #isA(Class)} and also the more complex {@link #and(char, char)},
+   * {@link #or(boolean, boolean)}, and {@link #not(double)}.
+   * 
+   * An {@link org.easymock.IExpectationSetters} object has methods which allow you to define
+   * the expected behaviour of the mocked method and the expected number of invocations,
+   * e.g. {@link org.easymock.IExpectationSetters#andReturn(Object)},
+   * {@link org.easymock.IExpectationSetters#andThrow(Throwable)}, and
+   * {@link org.easymock.IExpectationSetters#atLeastOnce()}.
+   * 
+   * @param expectedValue the parameter is used to transport the type to the ExpectationSetter.
+   * It allows writing the expected call as an argument,
+   * e.g. {@code expect(mock.getName()).andReturn("John Doe")}.
+   * @return the expectation setter.
+   */
+  public static <T> IExpectationSetters<T> expect(T expectedValue) {
+    return EasyMock.expect(expectedValue);
+  }
+
+  /**
+   * Returns the expectation setter for the last expected invocation in the
+   * current thread. This method is used for expected invocations on void
+   * methods. Use this for things such as
+   * {@link org.easymock.IExpectationSetters#andThrow(Throwable)}
+   * on void methods.
+   * E.g.
+   * {@code mock.doFoo();
+   * AndroidMock.expectLastCall().andThrow(new IllegalStateException());}
+   * 
+   * @see #expect(Object) for more details about {@link org.easymock.IExpectationSetters}
+   * @return the expectation setter.
+   */
+  public static <T> IExpectationSetters<T> expectLastCall() {
+    return EasyMock.expectLastCall();
+  }
+
+  /**
+   * Expects any {@code boolean} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyBoolean())).andReturn("hello world");}
+   * 
+   * @return {@code false}. The return value is always ignored.
+   */
+  public static boolean anyBoolean() {
+    return EasyMock.anyBoolean();
+  }
+
+  /**
+   * Expects any {@code byte} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyByte())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte anyByte() {
+    return EasyMock.anyByte();
+  }
+
+  /**
+   * Expects any {@code char} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyChar())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static char anyChar() {
+    return EasyMock.anyChar();
+  }
+
+  /**
+   * Expects any {@code int} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyInt())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int anyInt() {
+    return EasyMock.anyInt();
+  }
+
+  /**
+   * Expects any {@code long} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyLong())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long anyLong() {
+    return EasyMock.anyLong();
+  }
+
+  /**
+   * Expects any {@code float} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyFloat())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float anyFloat() {
+    return EasyMock.anyFloat();
+  }
+
+  /**
+   * Expects any {@code double} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyDouble())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.   */
+  public static double anyDouble() {
+    return EasyMock.anyDouble();
+  }
+
+  /**
+   * Expects any {@code short} argument as a parameter to a mocked method.
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyShort())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.   */
+  public static short anyShort() {
+    return EasyMock.anyShort();
+  }
+
+  /**
+   * Expects any {@code java.lang.Object} (or subclass) argument as a parameter to a mocked method.
+   * Note that this includes Arrays (since an array {@literal is an Object})
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.anyLong())).andReturn("hello world");}
+   * 
+   * @return {@code 0}. The return value is always ignored.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> T anyObject() {
+    return (T) EasyMock.anyObject();
+  }
+
+  /**
+   * Expects a {@code Comparable} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq("hi"))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T extends Comparable<T>> T geq(Comparable<T> expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code byte} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq((byte)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte geq(byte expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code double} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq(42.0))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double geq(double expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code float} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq(42.0f))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float geq(float expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects an {@code int} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq(42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int geq(int expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code long} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq(42l))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long geq(long expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code short} argument greater than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.geq((short)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short geq(short expectedValue) {
+    return EasyMock.geq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code Comparable} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq("hi"))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T extends Comparable<T>> T leq(Comparable<T> expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code byte} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq((byte)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte leq(byte expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code double} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq(42.0))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double leq(double expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code float} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq(42.0f))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float leq(float expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects an {@code int} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq(42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int leq(int expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code long} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq(42l))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long leq(long expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code short} argument less than or equal to the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.leq((short)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than or equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short leq(short expectedValue) {
+    return EasyMock.leq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code Comparable} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt("hi"))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T extends Comparable<T>> T gt(Comparable<T> expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code byte} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt((byte)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte gt(byte expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code double} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt(42.0))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double gt(double expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code float} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt(42.0f))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float gt(float expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects an {@code int} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt(42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int gt(int expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code long} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt(42l))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long gt(long expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code short} argument greater than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.gt((short)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be greater than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short gt(short expectedValue) {
+    return EasyMock.gt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code Comparable} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt("hi"))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T extends Comparable<T>> T lt(Comparable<T> expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code byte} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt((byte)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte lt(byte expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code double} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt(42.0))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double lt(double expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code float} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt(42.0f))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float lt(float expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects an {@code int} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt(42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int lt(int expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code long} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt(42l))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long lt(long expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects a {@code short} argument less than the given value as a parameter
+   * to a mocked method.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.lt((short)42))).andReturn("hello");}
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be less than.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short lt(short expectedValue) {
+    return EasyMock.lt(expectedValue);
+  }
+
+  /**
+   * Expects an object implementing the given class as a parameter to a mocked method. During
+   * replay mode, the mocked method call will accept any {@code Object} that is an instance of
+   * the specified class or one of its subclasses. Specifically, any {@code non-null} parameter for
+   * which the {@code java.lang.Class.isAssignableFrom(Class)} will return true will be accepted by
+   * this matcher during the replay phase.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.isA(HashMap.class))).andReturn("hello");}
+   * 
+   * @param <T> the expected Class type.
+   * @param clazz the class of the accepted type.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T> T isA(Class<T> clazz) {
+    return EasyMock.isA(clazz);
+  }
+
+  /**
+   * Expects a string that contains the given substring as a parameter to a mocked method.
+   * During replay mode, the mocked method will accept any {@code non-null String} which contains
+   * the provided {@code substring}.
+   * 
+   * Use this to loosen the expectations of acceptable parameters for a mocked method call.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.substring("hi"))).andReturn("hello");}
+   * 
+   * @param substring the substring which any incoming parameter to the mocked method must contain.
+   * @return {@code null}.
+   */
+  public static String contains(String substring) {
+    return EasyMock.contains(substring);
+  }
+
+  /**
+   * Expects a {@code boolean} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code boolean} that matches both of the
+   * provided expectations. Possible expectations for {@code first} and {@code second} include (but
+   * are not limited to) {@link #anyBoolean()} and {@link #eq(boolean)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(AndroidMock.anyBoolean(), AndroidMock.eq(true)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(anyBoolean(), eq(true)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code false}. The return value is always ignored.
+   */
+  public static boolean and(boolean first, boolean second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code byte} parameter that matches both of the provided expectations. During replay
+   * mode, the mocked method will accept any {@code byte} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyByte()}, {@link #leq(byte)} and {@link #eq(byte)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.and(
+   *        AndroidMock.gt((byte)0), AndroidMock.lt((byte)42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(gt((byte)0), lt((byte)42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte and(byte first, byte second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code char} parameter that matches both of the provided expectations. During replay
+   * mode, the mocked method will accept any {@code char} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyChar()} and {@link #eq(char)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(AndroidMock.geq('a'), AndroidMock.lt('q')))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(eq('a'), anyChar()))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static char and(char first, char second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code double} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code double} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyDouble()}, {@link #leq(double)} and {@link #eq(double)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(AndroidMock.gt(0.0), AndroidMock.lt(42.0)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(gt(0.0), lt(42.0)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double and(double first, double second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code float} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code float} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyFloat()}, {@link #leq(float)} and {@link #eq(float)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(AndroidMock.gt(0.0f), AndroidMock.lt(42.0f)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(gt(0.0f), lt(42.0f)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float and(float first, float second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects an {@code int} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code int} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyInt()}, {@link #leq(int)} and {@link #eq(int)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(AndroidMock.gt(0), AndroidMock.lt(42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(gt(0), lt(42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int and(int first, int second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code long} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code long} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyLong()}, {@link #leq(long)} and {@link #eq(long)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(AndroidMock.gt(0l), AndroidMock.lt(42l)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(gt(0l), lt(42l)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long and(long first, long second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code short} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code short} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyShort()}, {@link #leq(short)} and {@link #eq(short)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.and(
+   *        AndroidMock.gt((short)0), AndroidMock.lt((short)42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(gt((short)0), lt((short)42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short and(short first, short second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects an {@code Object} parameter that matches both of the provided expectations. During
+   * replay mode, the mocked method will accept any {@code Object} that matches both of the provided
+   * expectations. Possible expectations for {@code first} and {@code second} include (but are not
+   * limited to) {@link #anyObject()}, {@link #isA(Class)} and {@link #contains(String)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.and(
+   *            AndroidMock.contains("hi"), AndroidMock.contains("world")))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(contains("hi"), contains("world")))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static <T> T and(T first, T second) {
+    return EasyMock.and(first, second);
+  }
+
+  /**
+   * Expects a {@code boolean} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code boolean} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyBoolean()} and {@link #eq(boolean)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.or(AndroidMock.eq(true), AndroidMock.anyBoolean()))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(and(eq(true), anyBoolean()))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code false}. The return value is always ignored.
+   */
+  public static boolean or(boolean first, boolean second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code byte} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code byte} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyByte()}, {@link #eq(byte)},
+   * and {@link #lt(byte)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.geq((byte)0), AndroidMock.lt((byte)42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(geq((byte)0), lt((byte)42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte or(byte first, byte second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code char} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code char} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyChar()} and {@link #eq(char)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.eq('a'), AndroidMock.eq('z')))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(eq('a'), eq('z')))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static char or(char first, char second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code double} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code double} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyDouble()}, {@link #eq(double)}
+   * and {@link #lt(double)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.eq(0.0), AndroidMock.geq(42.0)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(eq(0.0), geq(42.0)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double or(double first, double second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code float} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code float} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyFloat()}, {@link #eq(float)}
+   * and {@link #lt(float)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.eq(0.0f), AndroidMock.geq(42.0f)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(eq(0.0f), geq(42.0f)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float or(float first, float second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects an {@code int} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code int} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyInt()}, {@link #eq(int)}
+   * and {@link #lt(int)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.eq(0), AndroidMock.geq(42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(eq(0), geq(42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int or(int first, int second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code long} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code long} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyLong()}, {@link #eq(long)}
+   * and {@link #lt(long)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.eq(0l), AndroidMock.geq(42l)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(eq(0l), geq(42l)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long or(long first, long second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code short} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code short} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyShort()}, {@link #eq(short)}
+   * and {@link #lt(short)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.eq((short)0), AndroidMock.geq((short)42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(eq((short)0), geq((short)42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short or(short first, short second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects an {@code Object} parameter that matches one or both of the provided expectations.
+   * During replay mode, the mocked method will accept any {@code Object} that matches one of the
+   * provided expectations, or both of them. Possible expectations for {@code first} and
+   * {@code second} include (but are not limited to) {@link #anyObject()}, {@link #eq(Class)}
+   * and {@link #lt(Comparable)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.or(
+   *        AndroidMock.notNull(), AndroidMock.geq(fortyTwo)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(or(notNull(), geq(fortyTwo)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param first the first expectation to test.
+   * @param second the second expectation to test.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T> T or(T first, T second) {
+    return EasyMock.or(first, second);
+  }
+
+  /**
+   * Expects a {@code boolean} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code boolean} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyBoolean()} and {@link #eq(boolean)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq(true)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq(true)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code false}. The return value is always ignored.
+   */
+  public static boolean not(boolean expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code byte} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code byte} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyByte()}, {@link #eq(byte)} and
+   * {@link #lt(byte)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq((byte)42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq((byte)42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static byte not(byte expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code char} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code char} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyChar()} and {@link #eq(char)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq('a')))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq('a')))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static char not(char expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code double} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code double} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyDouble()}, {@link #eq(double)} and
+   * {@link #lt(double)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq(42.0)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq(42.0)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double not(double expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code float} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code float} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyFloat()}, {@link #eq(float)} and
+   * {@link #lt(float)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq(42.0f)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq(42.0f)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float not(float expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code int} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code int} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyInt()}, {@link #eq(int)} and
+   * {@link #lt(int)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq(42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq(42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int not(int expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code long} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code long} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyLong()}, {@link #eq(long)} and
+   * {@link #lt(long)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq(42l)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq(42l)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long not(long expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code short} parameter that does not match the provided expectation.
+   * During replay mode, the mocked method will accept any {@code short} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyShort()}, {@link #eq(short)} and
+   * {@link #lt(short)}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq((short)42)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq((short)42)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short not(short expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects an {@code Object} parameter that does not match the given expectation.
+   * During replay mode, the mocked method will accept any {@code Object} that does not match
+   * the provided expectation. Possible expectations for {@code expectation}
+   * include (but are not limited to) {@link #anyObject()}, {@link #leq(Comparable)} and
+   * {@link #isNull()}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(
+   *        AndroidMock.not(AndroidMock.eq(fortyTwo)))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(not(eq(fortyTwo)))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectation the expectation to test.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static <T> T not(T expectation) {
+    return EasyMock.not(expectation);
+  }
+
+  /**
+   * Expects a {@code boolean} parameter that is equal to the provided {@code value}.
+   * During replay mode, the mocked method will accept any {@code boolean} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(true))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(true))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code false}. The return value is always ignored.
+   */
+  public static boolean eq(boolean expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code byte} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code byte} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq((byte)0))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq((byte)0))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code false}. The return value is always ignored.
+   */
+  public static byte eq(byte expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code char} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code char} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq('a'))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq('a'))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static char eq(char expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code double} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code double} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(0.0))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(0.0))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double eq(double expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code float} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code float} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(0.0f))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(0.0f))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float eq(float expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects an {@code int} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code int} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(0))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(0))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int eq(int expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code long} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code long} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(0l))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(0l))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long eq(long expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code short} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code short} that matches the
+   * value of {@code expectedValue}.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq((short)0))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq((short)0))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static short eq(short expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects an {@code Object} parameter that is equal to the provided {@code expectedValue}.
+   * During replay mode, the mocked method will accept any {@code Object} that matches the
+   * value of {@code expectedValue} according to its {@code equals(Object)} method.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq("hi"))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq("hi"))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the value to which the specified incoming parameter to the mocked method
+   * must be equal.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static <T> T eq(T expectedValue) {
+    return EasyMock.eq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code boolean} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myBooleanArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myBooleanArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static boolean[] aryEq(boolean[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code byte} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myByteArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myByteArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static byte[] aryEq(byte[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code char} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myCharArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myCharArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static char[] aryEq(char[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code double} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myDoubleArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myDoubleArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static double[] aryEq(double[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code float} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myFloatrArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myFloatArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static float[] aryEq(float[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects an {@code int} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myIntArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myIntArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static int[] aryEq(int[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code long} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myLongArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myLongArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static long[] aryEq(long[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code short} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myShortArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myShortArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static short[] aryEq(short[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects a {@code Object} array parameter that is equal to the given array, i.e. it has to
+   * have the same length, and each element has to be equal.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mock.getString(AndroidMock.eq(myObjectArray))).andReturn("hello");}
+   * 
+   * Or, for illustration purposes (using static imports)
+   * 
+   * {@code expect(mock.getString(eq(myObjectArray))).andReturn("hello");}
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param <T> the type of the array, it is passed through to prevent casts.
+   * @param expectedValue the array to which the specified incoming parameter to the mocked method
+   * must have equal contents.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T> T[] aryEq(T[] expectedValue) {
+    return EasyMock.aryEq(expectedValue);
+  }
+
+  /**
+   * Expects any {@code null} Object as a parameter.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @return {@code null}. The return value is always ignored.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> T isNull() {
+    return (T) EasyMock.isNull();
+  }
+
+  /**
+   * Expects any {@code non-null} Object parameter.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @return {@code null}. The return value is always ignored.
+   */
+  @SuppressWarnings("unchecked")
+  public static <T> T notNull() {
+    return (T) EasyMock.notNull();
+  }
+
+  /**
+   * Expects a {@code String} that contains a substring that matches the given regular
+   * expression as a parameter to the mocked method.
+   * 
+   * See {@link java.util.regex.Matcher#find()} for more details.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param regex the regular expression which must match some substring of the incoming parameter
+   * to the mocked method.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static String find(String regex) {
+    return EasyMock.find(regex);
+  }
+
+  /**
+   * Expects a {@code String} as a parameter to the mocked method, the entire length of which must
+   * match the given regular expression. This is not to be confused with {@link #find(String)} which
+   * matches the regular expression against any substring of the incoming parameter to the mocked
+   * method.
+   * 
+   * See {@link java.util.regex.Matcher#matches()} for more details.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param regex the regular expression against which the entire incoming parameter to the
+   * mocked method must match.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static String matches(String regex) {
+    return EasyMock.matches(regex);
+  }
+
+  /**
+   * Expects a {@code String} as a parameter to the mocked method that starts with the given prefix.
+   * 
+   * See {@link java.lang.String#startsWith(String)} for more details.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param prefix the string that is expected to match against the start of any incoming
+   * parameter to the mocked method.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static String startsWith(String prefix) {
+    return EasyMock.startsWith(prefix);
+  }
+
+  /**
+   * Expects a {@code String} as a parameter to the mocked method that ends with the given
+   * {@code suffix}.
+   * 
+   * See {@link java.lang.String#startsWith(String)} for more details.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param suffix the string that is expected to match against the end of any incoming
+   * parameter to the mocked method.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static String endsWith(String suffix) {
+    return EasyMock.endsWith(suffix);
+  }
+
+  /**
+   * Expects a {@code double} as a parameter to the mocked method that has an absolute difference to
+   * the given {@code expectedValue} that is less than the given {@code delta}.
+   * 
+   * The acceptable range of values is theoretically defined as any value {@code x} which satisfies
+   * the following inequality: {@code expectedValue - delta &lt;= x &lt;= expectedValue + delta}.
+   * 
+   * In practice, this is only true when {@code expectedValue + delta} and
+   * {@code expectedValue - delta} fall exactly on a precisely representable {@code double} value.
+   * Normally, the acceptable range of values is defined as any value {@code x} which satisfies the
+   * following inequality:
+   * {@code expectedValue - delta &lt; x &lt; expectedValue + delta}.
+   * 
+   * E.g. {@code AndroidMock.expect(mockObject.getString(
+   *    AndroidMock.eq(42.0, 0.1))).andReturn("hello world");}
+   * 
+   * The code snippet above will expect any {@code double} value greater than 41.9 and
+   * less than 42.1.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the center value of the expected range of values.
+   * @param delta the acceptable level of inaccuracy before this expectation fails.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double eq(double expectedValue, double delta) {
+    return EasyMock.eq(expectedValue, delta);
+  }
+
+  /**
+   * Expects a {@code float} as a parameter to the mocked method that has an absolute difference to
+   * the given {@code expectedValue} that is less than the given {@code delta}.
+   * 
+   * The acceptable range of values is theoretically defined as any value {@code x} which satisfies
+   * the following inequality: {@code expectedValue - delta &lt;= x &lt;= expectedValue + delta}.
+   * 
+   * In practice, this is only true when {@code expectedValue + delta} and
+   * {@code expectedValue - delta} fall exactly on a precisely representable {@code float} value.
+   * Normally, the acceptable range of values is defined as any value {@code x} which satisfies the
+   * following inequality:
+   * {@code expectedValue - delta &lt; x &lt; expectedValue + delta}.
+   * 
+   * E.g. {@code AndroidMock.expect(mockObject.getString(
+   *    AndroidMock.eq(42.0f, 0.1f))).andReturn("hello world");}
+   * 
+   * The code snippet above will expect any {@code float} value greater than 41.9 and
+   * less than 42.1.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the center value of the expected range of values.
+   * @param delta the acceptable level of inaccuracy before this expectation fails.
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float eq(float expectedValue, float delta) {
+    return EasyMock.eq(expectedValue, delta);
+  }
+
+  /**
+   * Expects an {@code Object} as a parameter to the mocked method that is the same as the given
+   * value. This expectation will fail unless the incoming parameter is {@code ==} to the
+   * {@code expectedValue} provided (i.e. the same {@code Object} reference).
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param <T> the type of the object, it is passed through to prevent casts.
+   * @param expectedValue the exact object which is expected during replay.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T> T same(T expectedValue) {
+    return EasyMock.same(expectedValue);
+  }
+
+  /**
+   * Expects a {@link java.lang.Comparable} argument equal to the given value according to
+   * its {@link java.lang.Comparable#compareTo(Object)} method.
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the {@link java.lang.Comparable} value which is expected to be equal to
+   * the incoming parameter to the mocked method according to the
+   * {@link java.lang.Comparable#compareTo(Object)} method.
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T extends Comparable<T>> T cmpEq(Comparable<T> expectedValue) {
+    return EasyMock.cmpEq(expectedValue);
+  }
+
+  /**
+   * Expects an argument that will be compared using the provided {@link java.util.Comparator}, the
+   * result of which will then be applied to the provided {@link org.easymock.LogicalOperator}
+   * (e.g. {@link org.easymock.LogicalOperator#LESS_THAN},
+   * {@link org.easymock.LogicalOperator#EQUAL},
+   * {@link org.easymock.LogicalOperator#GREATER_OR_EQUAL}).
+   * 
+   * The following comparison will take place:
+   * {@code comparator.compare(actual, expected) operator 0}
+   * 
+   * E.g.
+   * For illustration purposes (using static imports):
+   * 
+   * {@code
+   * expect(mockObject.getString(cmp("hi", CASE_INSENSITIVE_ORDER, LESS_THAN))).andReturn("hello");}
+   *
+   * {@code
+   * AndroidMock.expect(mockObject.getString(AndroidMock.cmp("hi", String.CASE_INSENSITIVE_ORDER,
+   *    LogicalOperator.LESS_THAN))).andReturn("hello");}
+   * 
+   * 
+   * The above invocation indicates that the call to {@code mockObject.getString(String)} is
+   * expecting any String which is lexically before "hi" (in a case insensitive ordering).
+   * 
+   * If this method is used for anything other than to set a parameter expectation as part of a
+   * mock object's recording phase, then an {@code IllegalStateException} will be thrown.
+   * 
+   * @param expectedValue the expected value against which the incoming method parameter will be
+   * compared.
+   * @param comparator {@link java.util.Comparator} used to perform the comparison between the
+   * expected value and the incoming parameter to the mocked method.
+   * @param operator The comparison operator, usually one of
+   * {@link org.easymock.LogicalOperator#LESS_THAN},
+   * {@link org.easymock.LogicalOperator#LESS_OR_EQUAL},
+   * {@link org.easymock.LogicalOperator#EQUAL}, {@link org.easymock.LogicalOperator#GREATER},
+   * {@link org.easymock.LogicalOperator#GREATER_OR_EQUAL} 
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T> T cmp(T expectedValue, Comparator<? super T> comparator,
+      LogicalOperator operator) {
+    return EasyMock.cmp(expectedValue, comparator, operator);
+  }
+
+  /**
+   * Expect any {@code Object} as a parameter to the mocked method, but capture it for later use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param <T> Type of the captured object
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code null}. The return value is always ignored.
+   */
+  public static <T> T capture(Capture<T> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Expect any {@code int/Integer} as a parameter to the mocked method, but capture it for later
+   * use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static int capture(Capture<Integer> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Expect any {@code long/Long} as a parameter to the mocked method, but capture it for later
+   * use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static long capture(Capture<Long> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Expect any {@code float/Float} as a parameter to the mocked method, but capture it for later
+   * use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static float capture(Capture<Float> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Expect any {@code double/Double} as a parameter to the mocked method, but capture it for later
+   * use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code 0}. The return value is always ignored.
+   */
+  public static double capture(Capture<Double> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Expect any {@code byte/Byte} as a parameter to the mocked method, but capture it for later
+   * use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code 0}
+   */
+  public static byte capture(Capture<Byte> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Expect any {@code char/Character} as a parameter to the mocked method, but capture it for later
+   * use.
+   * 
+   * {@link org.easymock.Capture} allows for capturing of the incoming value. Use
+   * {@link org.easymock.Capture#getValue()} to retrieve the captured value.
+   * 
+   * @param captured a container to hold the captured value, retrieved by
+   * {@link org.easymock.Capture#getValue()}
+   * @return {@code 0}
+   */
+  public static char capture(Capture<Character> captured) {
+    return EasyMock.capture(captured);
+  }
+
+  /**
+   * Switches the given mock objects (more exactly: the controls of the mock
+   * objects) to replay mode.
+   * 
+   * @param mocks the mock objects.
+   */
+  public static void replay(Object... mocks) {
+    for (Object mockObject : mocks) {
+      if (mockObject instanceof MockObject) {
+        EasyMock.replay(((MockObject) mockObject).getDelegate___AndroidMock());
+      } else {
+        EasyMock.replay(mockObject);
+      }
+    }
+  }
+
+  /**
+   * Resets the given mock objects (more exactly: the controls of the mock
+   * objects) allowing the mock objects to be reused.
+   * 
+   * @param mocks the mock objects.
+   */
+  public static void reset(Object... mocks) {
+    for (Object mockObject : mocks) {
+      if (mockObject instanceof MockObject) {
+        EasyMock.reset(((MockObject) mockObject).getDelegate___AndroidMock());
+      } else {
+        EasyMock.reset(mockObject);
+      }
+    }
+  }
+
+  /**
+   * Resets the given mock objects (more exactly: the controls of the mock
+   * objects) and change them in to mocks with nice behavior.
+   * {@link #createNiceMock(Class, Object...)} has more details.
+   * 
+   * @param mocks the mock objects
+   */
+  public static void resetToNice(Object... mocks) {
+    for (Object mockObject : mocks) {
+      if (mockObject instanceof MockObject) {
+        EasyMock.resetToNice(((MockObject) mockObject).getDelegate___AndroidMock());
+      } else {
+        EasyMock.resetToNice(mockObject);
+      }
+    }
+  }
+
+  /**
+   * Resets the given mock objects (more exactly: the controls of the mock
+   * objects) and turn them to a mock with default behavior. {@link #createMock(Class, Object...)}
+   * has more details.
+   * 
+   * @param mocks the mock objects
+   */
+  public static void resetToDefault(Object... mocks) {
+    for (Object mockObject : mocks) {
+      if (mockObject instanceof MockObject) {
+        EasyMock.resetToDefault(((MockObject) mockObject).getDelegate___AndroidMock());
+      } else {
+        EasyMock.resetToDefault(mockObject);
+      }
+    }
+  }
+
+  /**
+   * Resets the given mock objects (more exactly: the controls of the mock
+   * objects) and turn them to a mock with strict behavior.
+   * {@link #createStrictMock(Class, Object...)} has more details.
+   * 
+   * @param mocks the mock objects
+   */
+  public static void resetToStrict(Object... mocks) {
+    for (Object mockObject : mocks) {
+      if (mockObject instanceof MockObject) {
+        EasyMock.resetToStrict(((MockObject) mockObject).getDelegate___AndroidMock());
+      } else {
+        EasyMock.resetToStrict(mockObject);
+      }
+    }
+  }
+
+  /**
+   * Verifies that all of the expected method calls for the given mock objects (more exactly: the
+   * controls of the mock objects) have been executed.
+   * 
+   * The {@code verify} method captures the scenario where several methods were invoked correctly,
+   * but some invocations did not occur. Typically, the {@code verify} method is the final thing
+   * invoked in a test. 
+   * 
+   * @param mocks the mock objects.
+   */
+  public static void verify(Object... mocks) {
+    for (Object mockObject : mocks) {
+      if (mockObject instanceof MockObject) {
+        EasyMock.verify(((MockObject) mockObject).getDelegate___AndroidMock());
+      } else {
+        EasyMock.verify(mockObject);
+      }
+    }
+  }
+
+  /**
+   * Switches order checking of the given mock object (more exactly: the control
+   * of the mock object) on or off. When order checking is on, the mock will expect the method
+   * invokations to occur exactly in the order in which they appeared during the recording phase.
+   * 
+   * @param mock the mock object.
+   * @param orderCheckingOn {@code true} to turn order checking on, {@code false} to turn it off.
+   */
+  public static void checkOrder(Object mock, boolean orderCheckingOn) {
+    if (mock instanceof MockObject) {
+      EasyMock.checkOrder(((MockObject) mock).getDelegate___AndroidMock(), orderCheckingOn);
+    } else {
+      EasyMock.checkOrder(mock, orderCheckingOn);
+    }
+  }
+
+  /**
+   * Reports an argument matcher. This method is needed to define custom argument
+   * matchers.
+   * 
+   * For example:
+   * 
+   * {@code
+   * AndroidMock.reportMatcher(new IntIsFortyTwo());
+   * AndroidMock.expect(mockObject.getString(null)).andReturn("hello world");}
+   * 
+   * This example will expect a parameter for {@code mockObject.getString(int)} that matches the
+   * conditions required by the {@code matches} method as defined by
+   * {@link org.easymock.IArgumentMatcher#matches(Object)}.
+   * 
+   * @param matcher the matcher whose {@code matches} method will be applied to the incoming
+   * parameter to the mocked method.
+   */
+  public static void reportMatcher(IArgumentMatcher matcher) {
+    EasyMock.reportMatcher(matcher);
+  }
+
+  /**
+   * Returns the arguments of the current mock method call, if inside an
+   * {@code IAnswer} callback - be careful here, reordering parameters of a
+   * method changes the semantics of your tests.
+   * 
+   * This method is only usable within an {@link org.easymock.IAnswer} instance. Attach an
+   * {@link org.easymock.IAnswer} to an expectation by using the
+   * {@link org.easymock.IExpectationSetters#andAnswer(org.easymock.IAnswer)} method.
+   * 
+   * E.g.
+   * {@code AndroidMock.expect(mockObject.getString()).andAnswer(myAnswerCallback);}
+   * 
+   * @return the arguments of the current mock method call.
+   * @throws IllegalStateException if called outside of {@code IAnswer}
+   *         callbacks.
+   */
+  public static Object[] getCurrentArguments() {
+    return EasyMock.getCurrentArguments();
+  }
+
+  /**
+   * Makes the mock thread safe. The mock will be usable in a multithreaded
+   * environment.
+   * 
+   * @param mock the mock to make thread safe.
+   * @param threadSafe If the mock should be thread safe or not.
+   */
+  public static void makeThreadSafe(Object mock, boolean threadSafe) {
+    if (mock instanceof MockObject) {
+      EasyMock.makeThreadSafe(((MockObject) mock).getDelegate___AndroidMock(), threadSafe);
+    } else {
+      EasyMock.makeThreadSafe(mock, threadSafe);
+    }
+  }
+
+  @SuppressWarnings("unchecked")
+  private static <T, S> T getSubclassFor(Class<? super T> clazz, Class<S> delegateInterface,
+      Object realMock, Object... args) {
+    Class<T> subclass;
+    String className = null;
+    try {
+      if (isAndroidClass(clazz)) {
+        className = FileUtils.getSubclassNameFor(clazz, SdkVersion.getCurrentVersion());
+      } else {
+        className = FileUtils.getSubclassNameFor(clazz, SdkVersion.UNKNOWN);
+      }
+      subclass = (Class<T>) Class.forName(className);
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException("Could not find class for " + className
+          + " which likely means that the mock-instrumented jar has not been created or else"
+          + " is not being used in the current runtime environment. Try running MockGeneratorMain"
+          + " in MockGenerator_deploy.jar or using the output of that execution as the input to"
+          + " the dex/apk generation.", e);
+    }
+    Constructor<T> constructor = getConstructorFor(subclass, args);
+    T newObject;
+    try {
+      newObject = constructor.newInstance(args);
+    } catch (InstantiationException e) {
+      throw new RuntimeException("Internal error instantiating new mock subclass"
+          + subclass.getName(), e);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException(
+          "Internal error - the new mock subclass' constructor was inaccessible", e);
+    } catch (InvocationTargetException e) {
+      throw new ExceptionInInitializerError(e);
+    }
+    Method[] methods = subclass.getMethods();
+    Method setMethod;
+    try {
+      setMethod = subclass.getMethod("setDelegate___AndroidMock", delegateInterface);
+    } catch (NoSuchMethodException e) {
+      throw new RuntimeException("Internal error - No setDelegate method found for " + "class "
+          + subclass.getName() + " and param " + delegateInterface.getName(), e);
+    }
+    try {
+      setMethod.invoke(newObject, realMock);
+    } catch (IllegalArgumentException e) {
+      throw new IllegalArgumentException("Internal error setting the delegate, expected "
+          + newObject.getClass() + " to be subclass of " + clazz.getName());
+    } catch (InvocationTargetException e) {
+      throw new RuntimeException("Severe internal error, setDelegate threw an exception", e);
+    } catch (IllegalAccessException e) {
+      throw new RuntimeException("Internal error, setDelegate method was inaccessible", e);
+    }
+    return newObject;
+  }
+  
+  static boolean isUnboxableToPrimitive(Class<?> clazz, Object arg, boolean exactMatch) {
+    if (!clazz.isPrimitive()) {
+      throw new IllegalArgumentException(
+          "Internal Error - The class to test against is not a primitive");
+    }
+    Class<?> unboxedType = null;
+    if (arg.getClass().equals(Integer.class)) {
+      unboxedType = Integer.TYPE;
+    } else if (arg.getClass().equals(Long.class)) {
+      unboxedType = Long.TYPE;
+    } else if (arg.getClass().equals(Byte.class)) {
+      unboxedType = Byte.TYPE;
+    } else if (arg.getClass().equals(Short.class)) {
+      unboxedType = Short.TYPE;
+    } else if (arg.getClass().equals(Character.class)) {
+      unboxedType = Character.TYPE;
+    } else if (arg.getClass().equals(Float.class)) {
+      unboxedType = Float.TYPE;
+    } else if (arg.getClass().equals(Double.class)) {
+      unboxedType = Double.TYPE;
+    } else if (arg.getClass().equals(Boolean.class)) {
+      unboxedType = Boolean.TYPE;
+    } else {
+      return false;
+    }
+    if (exactMatch) {
+      return clazz == unboxedType;
+    }
+    return isAssignable(clazz, unboxedType);
+  }
+  
+  private static boolean isAssignable(Class<?> to, Class<?> from) {
+    if (to == Byte.TYPE) {
+      return from == Byte.TYPE;
+    } else if (to == Short.TYPE){
+      return from == Byte.TYPE || from == Short.TYPE || from == Character.TYPE;
+    } else if (to == Integer.TYPE || to == Character.TYPE) {
+      return from == Byte.TYPE || from == Short.TYPE || from == Integer.TYPE
+          || from == Character.TYPE;
+    } else if (to == Long.TYPE) {
+      return from == Byte.TYPE || from == Short.TYPE || from == Integer.TYPE || from == Long.TYPE
+          || from == Character.TYPE;
+    } else if (to == Float.TYPE) {
+      return from == Byte.TYPE || from == Short.TYPE || from == Integer.TYPE
+          || from == Character.TYPE || from == Float.TYPE;
+    } else if (to == Double.TYPE) {
+      return from == Byte.TYPE || from == Short.TYPE || from == Integer.TYPE || from == Long.TYPE
+          || from == Character.TYPE || from == Float.TYPE || from == Double.TYPE;
+    } else if (to == Boolean.TYPE) {
+      return from == Boolean.TYPE;
+    } else {
+      return to.isAssignableFrom(from);
+    }
+  }
+  
+  @SuppressWarnings("unchecked")
+  static <T> Constructor<T> getConstructorFor(Class<T> clazz, Object... args)
+      throws SecurityException {
+    Constructor<T>[] constructors = (Constructor<T>[]) clazz.getConstructors();
+    Constructor<T> compatibleConstructor = null;
+    for (Constructor<T> constructor : constructors) {
+      Class<?>[] params = constructor.getParameterTypes();
+      if (params.length == args.length) {
+        boolean exactMatch = true;
+        boolean compatibleMatch = true;
+        for (int i = 0; i < params.length; ++i) {
+          Object arg = args[i];
+          if (arg == null) {
+            arg = Void.TYPE;
+          }
+          if (!params[i].isAssignableFrom(arg.getClass())) {
+            if (params[i].isPrimitive()) {
+              exactMatch &= isUnboxableToPrimitive(params[i], arg, true);
+              compatibleMatch &= isUnboxableToPrimitive(params[i], arg, false);
+            } else {
+              exactMatch = false;
+              compatibleMatch = false;
+            }
+          }
+        }
+        if (exactMatch) {
+          return constructor;
+        } else if (compatibleMatch) {
+          compatibleConstructor = constructor;
+        }
+      }
+    }
+    if (compatibleConstructor != null) {
+      return compatibleConstructor;
+    }
+    List<String> argTypes = new ArrayList<String>(args.length);
+    for (Object arg : args) {
+      argTypes.add(arg == null ? "<null>" : arg.getClass().toString());
+    }
+    throw new IllegalArgumentException("Could not find the specified Constructor: "
+        + clazz.getName() + "(" + argTypes + ")");
+  }
+
+  @SuppressWarnings("unchecked")
+  private static <T> Class<T> getInterfaceFor(Class<T> clazz) {
+    try {
+      String className;
+      if (isAndroidClass(clazz)) {
+        className = FileUtils.getInterfaceNameFor(clazz, SdkVersion.getCurrentVersion());
+      } else {
+        className = FileUtils.getInterfaceNameFor(clazz, SdkVersion.UNKNOWN);
+      }
+      return (Class<T>) Class.forName(className);
+    } catch (ClassNotFoundException e) {
+      throw new RuntimeException("Could not find mock for " + clazz.getName()
+          + "  -- Make sure to run the MockGenerator.jar on your test jar, and to "
+          + "build the Android test APK using the modified jar created by MockGenerator", e);
+    }
+  }
+
+  static boolean isAndroidClass(Class<?> clazz) {
+    String packageName = clazz.getPackage().getName();
+    return packageName.startsWith("android.") || packageName.startsWith("dalvik.")
+        || packageName.startsWith("java.") || packageName.startsWith("javax.")
+        || packageName.startsWith("org.xml.sax") || packageName.startsWith("org.xmlpull.v1")
+        || packageName.startsWith("org.w3c.dom") || packageName.startsWith("org.apache.http")
+        || packageName.startsWith("junit.");
+  }
+}
diff --git a/src/com/google/android/testing/mocking/AndroidMockGenerator.java b/src/com/google/android/testing/mocking/AndroidMockGenerator.java
new file mode 100644
index 0000000..1a557a6
--- /dev/null
+++ b/src/com/google/android/testing/mocking/AndroidMockGenerator.java
@@ -0,0 +1,480 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+import javassist.ClassClassPath;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtConstructor;
+import javassist.CtField;
+import javassist.CtMethod;
+import javassist.CtNewConstructor;
+import javassist.NotFoundException;
+
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * AndroidMockGenerator creates the subclass and interface required for mocking
+ * a given Class.
+ * 
+ * The only public method of AndroidMockGenerator is createMocksForClass. See
+ * the javadocs for this method for more information about AndroidMockGenerator.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+class AndroidMockGenerator {
+  public AndroidMockGenerator() {
+    ClassPool.doPruning = false;
+    ClassPool.getDefault().insertClassPath(new ClassClassPath(MockObject.class));
+  }
+
+  /**
+   * Creates a List of javassist.CtClass objects representing all of the
+   * interfaces and subclasses required to meet the Mocking requests of the
+   * Class specified by {@code clazz}.
+   * 
+   * A test class can request that a Class be prepared for mocking by using the
+   * {@link UsesMocks} annotation at either the Class or Method level. All
+   * classes specified by these annotations will have exactly two CtClass
+   * objects created, one for a generated interface, and one for a generated
+   * subclass. The interface and subclass both define the same methods which
+   * comprise all of the mockable methods of the provided class. At present, for
+   * a method to be mockable, it must be non-final and non-static, although this
+   * may expand in the future.
+   * 
+   * The class itself must be mockable, otherwise this method will ignore the
+   * requested mock and print a warning. At present, a class is mockable if it
+   * is a non-final publicly-instantiable Java class that is assignable from the
+   * java.lang.Object class. See the javadocs for
+   * {@link java.lang.Class#isAssignableFrom(Class)} for more information about
+   * what "is assignable from the Object class" means. As a non-exhaustive
+   * example, if a given Class represents an Enum, Annotation, Primitive or
+   * Array, then it is not assignable from Object. Interfaces are also ignored
+   * since these need no modifications in order to be mocked.
+   * 
+   * @param clazz the Class object to have all of its UsesMocks annotations
+   *        processed and the corresponding Mock Classes created.
+   * @return a List of CtClass objects representing the Classes and Interfaces
+   *         required for mocking the classes requested by {@code clazz}
+   * @throws ClassNotFoundException
+   * @throws CannotCompileException
+   * @throws IOException
+   */
+  public List<GeneratedClassFile> createMocksForClass(Class<?> clazz)
+      throws ClassNotFoundException, IOException, CannotCompileException {
+    return this.createMocksForClass(clazz, SdkVersion.UNKNOWN);
+  }
+
+  public List<GeneratedClassFile> createMocksForClass(Class<?> clazz, SdkVersion sdkVersion)
+      throws ClassNotFoundException, IOException, CannotCompileException {
+    if (!classIsSupportedType(clazz)) {
+      reportReasonForUnsupportedType(clazz);
+      return Arrays.asList(new GeneratedClassFile[0]);
+    }
+    CtClass newInterfaceCtClass = generateInterface(clazz, sdkVersion);
+    GeneratedClassFile newInterface = new GeneratedClassFile(newInterfaceCtClass.getName(),
+        newInterfaceCtClass.toBytecode());
+    CtClass mockDelegateCtClass = generateSubClass(clazz, newInterfaceCtClass, sdkVersion);
+    GeneratedClassFile mockDelegate = new GeneratedClassFile(mockDelegateCtClass.getName(),
+        mockDelegateCtClass.toBytecode());
+    return Arrays.asList(new GeneratedClassFile[] {newInterface, mockDelegate});
+  }
+
+  private void reportReasonForUnsupportedType(Class<?> clazz) {
+    String reason = null;
+    if (clazz.isInterface()) {
+      // do nothing to make sure none of the other conditions apply.
+    } else if (clazz.isEnum()) {
+      reason = "Cannot mock an Enum";
+    } else if (clazz.isAnnotation()) {
+      reason = "Cannot mock an Annotation";
+    } else if (clazz.isArray()) {
+      reason = "Cannot mock an Array";
+    } else if (Modifier.isFinal(clazz.getModifiers())) {
+      reason = "Cannot mock a Final class";
+    } else if (clazz.isPrimitive()) {
+      reason = "Cannot mock primitives";
+    } else if (!Object.class.isAssignableFrom(clazz)) {
+      reason = "Cannot mock non-classes";
+    } else if (!containsUsableConstructor(clazz)) {
+      reason = "Cannot mock a class with no public constructors";
+    } else {
+      // Whatever the reason is, it's not one that we care about.
+    }
+    if (reason != null) {
+      // Sometimes we want to be silent, so check 'reason' against null.
+      System.err.println(reason + ": " + clazz.getName());
+    }
+  }
+  
+  private boolean containsUsableConstructor(Class<?> clazz) {
+    Constructor<?>[] constructors = clazz.getDeclaredConstructors();
+    for (Constructor<?> constructor : constructors) {
+      if (Modifier.isPublic(constructor.getModifiers()) ||
+          Modifier.isProtected(constructor.getModifiers())) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  boolean classIsSupportedType(Class<?> clazz) {
+    return (containsUsableConstructor(clazz)) && Object.class.isAssignableFrom(clazz)
+        && !clazz.isInterface() && !clazz.isEnum() && !clazz.isAnnotation() && !clazz.isArray()
+        && !Modifier.isFinal(clazz.getModifiers());
+  }
+
+  void saveCtClass(CtClass clazz) throws ClassNotFoundException, IOException {
+    try {
+      clazz.writeFile();
+    } catch (NotFoundException e) {
+      throw new ClassNotFoundException("Error while saving modified class " + clazz.getName(), e);
+    } catch (CannotCompileException e) {
+      throw new RuntimeException("Internal Error: Attempt to save syntactically incorrect code "
+          + "for class " + clazz.getName(), e);
+    }
+  }
+
+  CtClass generateInterface(Class<?> originalClass, SdkVersion sdkVersion) {
+    ClassPool classPool = getClassPool();
+    try {
+      return classPool.getCtClass(FileUtils.getInterfaceNameFor(originalClass, sdkVersion));
+    } catch (NotFoundException e) {
+      CtClass newInterface =
+          classPool.makeInterface(FileUtils.getInterfaceNameFor(originalClass, sdkVersion));
+      addInterfaceMethods(originalClass, newInterface);
+      return newInterface;
+    }
+  }
+
+  String getInterfaceMethodSource(Method method) throws UnsupportedOperationException {
+    StringBuilder methodBody = getMethodSignature(method);
+    methodBody.append(";");
+    return methodBody.toString();
+  }
+
+  private StringBuilder getMethodSignature(Method method) {
+    int modifiers = method.getModifiers();
+    if (Modifier.isFinal(modifiers) || Modifier.isStatic(modifiers)) {
+      throw new UnsupportedOperationException(
+          "Cannot specify final or static methods in an interface");
+    }
+    StringBuilder methodSignature = new StringBuilder("public ");
+    methodSignature.append(getClassName(method.getReturnType()));
+    methodSignature.append(" ");
+    methodSignature.append(method.getName());
+    methodSignature.append("(");
+    int i = 0;
+    for (Class<?> arg : method.getParameterTypes()) {
+      methodSignature.append(getClassName(arg));
+      methodSignature.append(" arg");
+      methodSignature.append(i);
+      if (i < method.getParameterTypes().length - 1) {
+        methodSignature.append(",");
+      }
+      i++;
+    }
+    methodSignature.append(")");
+    if (method.getExceptionTypes().length > 0) {
+      methodSignature.append(" throws ");
+    }
+    i = 0;
+    for (Class<?> exception : method.getExceptionTypes()) {
+      methodSignature.append(getClassName(exception));
+      if (i < method.getExceptionTypes().length - 1) {
+        methodSignature.append(",");
+      }
+      i++;
+    }
+    return methodSignature;
+  }
+
+  private String getClassName(Class<?> clazz) {
+    return clazz.getCanonicalName();
+  }
+
+  static ClassPool getClassPool() {
+    return ClassPool.getDefault();
+  }
+
+  private boolean classExists(String name) {
+    // The following line is the ideal, but doesn't work (bug in library).
+    // return getClassPool().find(name) != null;
+    try {
+      getClassPool().get(name);
+      return true;
+    } catch (NotFoundException e) {
+      return false;
+    }
+  }
+
+  CtClass generateSubClass(Class<?> superClass, CtClass newInterface, SdkVersion sdkVersion)
+      throws ClassNotFoundException {
+    if (classExists(FileUtils.getSubclassNameFor(superClass, sdkVersion))) {
+      try {
+        return getClassPool().get(FileUtils.getSubclassNameFor(superClass, sdkVersion));
+      } catch (NotFoundException e) {
+        throw new ClassNotFoundException("This should be impossible, since we just checked for "
+            + "the existence of the class being created", e);
+      }
+    }
+    CtClass newClass = generateSkeletalClass(superClass, newInterface, sdkVersion);
+    if (!newClass.isFrozen()) {
+      newClass.addInterface(newInterface);
+      try {
+        newClass.addInterface(getClassPool().get(MockObject.class.getName()));
+      } catch (NotFoundException e) {
+        throw new ClassNotFoundException("Could not find " + MockObject.class.getName(), e);
+      }
+      addMethods(superClass, newClass);
+      addGetDelegateMethod(newClass);
+      addSetDelegateMethod(newClass, newInterface);
+      addConstructors(newClass, superClass);
+    }
+    return newClass;
+  }
+  
+  private void addConstructors(CtClass clazz, Class<?> superClass) throws ClassNotFoundException {
+    CtClass superCtClass = getCtClassForClass(superClass);
+    
+    CtConstructor[] constructors = superCtClass.getDeclaredConstructors();
+    for (CtConstructor constructor : constructors) {
+      int modifiers = constructor.getModifiers();
+      if (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers)) {
+         CtConstructor ctConstructor;
+        try {
+          ctConstructor = CtNewConstructor.make(constructor.getParameterTypes(),
+               constructor.getExceptionTypes(), clazz);
+          clazz.addConstructor(ctConstructor);
+        } catch (CannotCompileException e) {
+          throw new RuntimeException("Internal Error - Could not add constructors.", e);
+        } catch (NotFoundException e) {
+          throw new RuntimeException("Internal Error - Constructor suddenly could not be found", e);
+        }
+      }
+    }
+  }
+
+  CtClass getCtClassForClass(Class<?> clazz) throws ClassNotFoundException {
+    ClassPool classPool = getClassPool();
+    try {
+      return classPool.get(clazz.getName());
+    } catch (NotFoundException e) {
+      throw new ClassNotFoundException("Class not found when finding the class to be mocked: "
+          + clazz.getName(), e);
+    }
+  }
+
+  private void addSetDelegateMethod(CtClass clazz, CtClass newInterface) {
+    try {
+      clazz.addMethod(CtMethod.make(getSetDelegateMethodSource(newInterface), clazz));
+    } catch (CannotCompileException e) {
+      throw new RuntimeException("Internal error while creating the setDelegate() method", e);
+    }
+  }
+
+  String getSetDelegateMethodSource(CtClass newInterface) {
+    return "public void setDelegate___AndroidMock(" + newInterface.getName() + " obj) { this."
+        + getDelegateFieldName() + " = obj;}";
+  }
+
+  private void addGetDelegateMethod(CtClass clazz) {
+    try {
+      CtMethod newMethod = CtMethod.make(getGetDelegateMethodSource(), clazz);
+      try {
+        CtMethod existingMethod = clazz.getMethod(newMethod.getName(), newMethod.getSignature());
+        clazz.removeMethod(existingMethod);
+      } catch (NotFoundException e) {
+        // expected path... sigh.
+      }
+      clazz.addMethod(newMethod);
+    } catch (CannotCompileException e) {
+      throw new RuntimeException("Internal error while creating the getDelegate() method", e);
+    }
+  }
+
+  private String getGetDelegateMethodSource() {
+    return "public Object getDelegate___AndroidMock() { return this." + getDelegateFieldName()
+        + "; }";
+  }
+
+  String getDelegateFieldName() {
+    return "delegateMockObject";
+  }
+
+  void addInterfaceMethods(Class<?> originalClass, CtClass newInterface) {
+    Method[] methods = getAllMethods(originalClass);
+    for (Method method : methods) {
+      try {
+        if (isMockable(method)) {
+          CtMethod newMethod = CtMethod.make(getInterfaceMethodSource(method), newInterface);
+          newInterface.addMethod(newMethod);
+        }
+      } catch (UnsupportedOperationException e) {
+        // Can't handle finals and statics.
+      } catch (CannotCompileException e) {
+        throw new RuntimeException(
+            "Internal error while creating a new Interface method for class "
+                + originalClass.getName() + ".  Method name: " + method.getName(), e);
+      }
+    }
+  }
+
+  void addMethods(Class<?> superClass, CtClass newClass) {
+    Method[] methods = getAllMethods(superClass);
+    if (newClass.isFrozen()) {
+      newClass.defrost();
+    }
+    List<CtMethod> existingMethods = Arrays.asList(newClass.getDeclaredMethods());
+    for (Method method : methods) {
+      try {
+        if (isMockable(method)) {
+          CtMethod newMethod = CtMethod.make(getDelegateMethodSource(method), newClass);
+          if (!existingMethods.contains(newMethod)) {
+            newClass.addMethod(newMethod);
+          }
+        }
+      } catch (UnsupportedOperationException e) {
+        // Can't handle finals and statics.
+      } catch (CannotCompileException e) {
+        throw new RuntimeException("Internal Error while creating subclass methods for "
+            + newClass.getName() + " method: " + method.getName(), e);
+      }
+    }
+  }
+
+  Method[] getAllMethods(Class<?> clazz) {
+    Map<String, Method> methodMap = getAllMethodsMap(clazz);
+    return methodMap.values().toArray(new Method[0]);
+  }
+
+  private Map<String, Method> getAllMethodsMap(Class<?> clazz) {
+    Map<String, Method> methodMap = new HashMap<String, Method>();
+    Class<?> superClass = clazz.getSuperclass();
+    if (superClass != null) {
+      methodMap.putAll(getAllMethodsMap(superClass));
+    }
+    List<Method> methods = new ArrayList<Method>(Arrays.asList(clazz.getDeclaredMethods()));
+    for (Method method : methods) {
+      String key = method.getName();
+      for (Class<?> param : method.getParameterTypes()) {
+        key += param.getCanonicalName();
+      }
+      methodMap.put(key, method);
+    }
+    return methodMap;
+  }
+
+  boolean isMockable(Method method) {
+    if (isForbiddenMethod(method)) {
+      return false;
+    }
+    int modifiers = method.getModifiers();
+    return !Modifier.isFinal(modifiers) && !Modifier.isStatic(modifiers) && !method.isBridge()
+        && (Modifier.isPublic(modifiers) || Modifier.isProtected(modifiers));
+  }
+
+  boolean isForbiddenMethod(Method method) {
+    if (method.getName().equals("equals")) {
+      return method.getParameterTypes().length == 1
+          && method.getParameterTypes()[0].equals(Object.class);
+    } else if (method.getName().equals("toString")) {
+      return method.getParameterTypes().length == 0;
+    } else if (method.getName().equals("hashCode")) {
+      return method.getParameterTypes().length == 0;
+    }
+    return false;
+  }
+
+  private String getReturnDefault(Method method) {
+    Class<?> returnType = method.getReturnType();
+    if (!returnType.isPrimitive()) {
+      return "null";
+    } else if (returnType == Boolean.TYPE) {
+      return "false";
+    } else if (returnType == Void.TYPE) {
+      return "";
+    } else {
+      return "(" + returnType.getName() + ")0";
+    }
+  }
+  
+  String getDelegateMethodSource(Method method) {
+    StringBuilder methodBody = getMethodSignature(method);
+    methodBody.append("{");
+    methodBody.append("if(this.");
+    methodBody.append(getDelegateFieldName());
+    methodBody.append("==null){return ");
+    methodBody.append(getReturnDefault(method));
+    methodBody.append(";}");
+    if (!method.getReturnType().equals(Void.TYPE)) {
+      methodBody.append("return ");
+    }
+    methodBody.append("this.");
+    methodBody.append(getDelegateFieldName());
+    methodBody.append(".");
+    methodBody.append(method.getName());
+    methodBody.append("(");
+    for (int i = 0; i < method.getParameterTypes().length; ++i) {
+      methodBody.append("arg");
+      methodBody.append(i);
+      if (i < method.getParameterTypes().length - 1) {
+        methodBody.append(",");
+      }
+    }
+    methodBody.append(");}");
+    return methodBody.toString();
+  }
+
+  CtClass generateSkeletalClass(Class<?> superClass, CtClass newInterface, SdkVersion sdkVersion)
+      throws ClassNotFoundException {
+    ClassPool classPool = getClassPool();
+    CtClass superCtClass = getCtClassForClass(superClass);
+    String subclassName = FileUtils.getSubclassNameFor(superClass, sdkVersion);
+
+    CtClass newClass;
+    try {
+      newClass = classPool.makeClass(subclassName, superCtClass);
+    } catch (RuntimeException e) {
+      if (e.getMessage().contains("frozen class")) {
+        try {
+          return classPool.get(subclassName);
+        } catch (NotFoundException ex) {
+          throw new ClassNotFoundException("Internal Error: could not find class", ex);
+        }
+      }
+      throw e;
+    }
+
+    try {
+      newClass.addField(new CtField(newInterface, getDelegateFieldName(), newClass));
+    } catch (CannotCompileException e) {
+      throw new RuntimeException("Internal error adding the delegate field to "
+          + newClass.getName(), e);
+    }
+    return newClass;
+  }
+}
diff --git a/src/com/google/android/testing/mocking/FileUtils.java b/src/com/google/android/testing/mocking/FileUtils.java
new file mode 100644
index 0000000..f759c57
--- /dev/null
+++ b/src/com/google/android/testing/mocking/FileUtils.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class FileUtils {
+
+  /**
+   * @param clazz
+   * @param sdkVersion
+   * @return the appropriate interface name for the interface mock support file.
+   */
+  static String getInterfaceNameFor(Class<?> clazz, SdkVersion sdkVersion) {
+    return sdkVersion.getPackagePrefix() + "genmocks." + clazz.getName() + "DelegateInterface";
+  }
+  /**
+   * @param clazz
+   * @param sdkVersion
+   * @return the appropriate subclass name for the subclass mock support file.
+   */
+  static String getSubclassNameFor(Class<?> clazz, SdkVersion sdkVersion) {
+    return sdkVersion.getPackagePrefix() + "genmocks." + clazz.getName() + "DelegateSubclass";
+  }
+
+  /**
+   * Converts a class name into the a .class filename.
+   * 
+   * @param className
+   * @return the file name for the specified class name.
+   */
+  static String getFilenameFor(String className) {
+    return className.replace('.', File.separatorChar) + ".class";
+  }
+
+  /**
+   * Converts a filename into a class name.
+   * 
+   * @param filename
+   * @return the class name for the specified file name.
+   */
+  static String getClassNameFor(String filename) {
+    if (!filename.endsWith(".class")) {
+      throw new IllegalArgumentException("Argument provided is not a class filename: " + filename);
+    }
+    return filename.replace(File.separatorChar, '.').substring(0, filename.length() - 6);
+  }
+
+  static void saveClassToFolder(GeneratedClassFile clazz, String outputFolderName)
+      throws FileNotFoundException, IOException {
+    File classFolder = new File(outputFolderName);
+    File targetFile = new File(classFolder, getFilenameFor(clazz.getClassName()));
+    targetFile.getParentFile().mkdirs();
+    FileOutputStream outputStream = new FileOutputStream(targetFile);
+    outputStream.write(clazz.getContents());
+    outputStream.close();
+  }
+}
diff --git a/src/com/google/android/testing/mocking/GeneratedClassFile.java b/src/com/google/android/testing/mocking/GeneratedClassFile.java
new file mode 100644
index 0000000..1ef01ed
--- /dev/null
+++ b/src/com/google/android/testing/mocking/GeneratedClassFile.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Represents the contents of a Class file.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class GeneratedClassFile {
+  private final String className;
+  private final byte[] contents;
+
+  /**
+   * @param name the fully qualified name of the class.
+   * @param classFileContents the binary contents of the file.
+   */
+  public GeneratedClassFile(String name, byte[] classFileContents) {
+    className = name;
+    contents = classFileContents;
+  }
+
+  public String getClassName() {
+    return className;
+  }
+
+  public byte[] getContents() {
+    return contents;
+  }
+
+  @Override
+  public int hashCode() {
+    return (this.getClass().getName() + className).hashCode();
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    return (obj instanceof GeneratedClassFile)
+      && className.equals(((GeneratedClassFile) obj).getClassName());
+  }
+}
diff --git a/src/com/google/android/testing/mocking/GeneratedMockJar.readme b/src/com/google/android/testing/mocking/GeneratedMockJar.readme
new file mode 100644
index 0000000..858ec6f
--- /dev/null
+++ b/src/com/google/android/testing/mocking/GeneratedMockJar.readme
@@ -0,0 +1,32 @@
+Android Mock
+
+Copyright 2010 Google Inc.
+All Rights Reserved.
+Author: swoodward@google.com (Stephen Woodward)
+
+
+Android Mock is a wrapper for EasyMock (2.4) which allows for real Class mocking on
+an Android (Dalvik) VM.
+
+All methods on Android Mock are syntactically equivalent to EasyMock method
+calls, and will delegate calls to EasyMock, while performing the required
+transformations to avoid Dalvik VM troubles.
+
+Calls directly to EasyMock will work correctly only if the Class being mocked
+is in fact an Interface. Calls to Android Mock will work correctly for both
+Interfaces and concrete Classes.
+
+Android Mock requires that the code being mocked be instrumented prior to
+loading to the Dalvik VM by having called the MockGenerator.jar file. Try
+running java -jar MockGenerator.jar --help for more information.
+
+An example usage pattern is:
+
+@UsesMocks(MyClass.class)
+public void testFoo() MyClass {
+  mockObject = AndroidMock.createMock(MyClass.class);
+  AndroidMock.expect(mockObject.foo(0)).andReturn(42);
+  AndroidMock.replay(mockObject); assertEquals(42, mockObject.foo(0));
+  AndroidMock.verify(mockObject);
+}
+
diff --git a/src/com/google/android/testing/mocking/MockObject.java b/src/com/google/android/testing/mocking/MockObject.java
new file mode 100644
index 0000000..513c900
--- /dev/null
+++ b/src/com/google/android/testing/mocking/MockObject.java
@@ -0,0 +1,32 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Defines the getDelegate___AndroidMock method used by Android Mock for
+ * delegating Android Mock calls to the EasyMock generated MockObject.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public interface MockObject {
+  /**
+   * Accessor method to get the wrapped EasyMock mock object.
+   * 
+   * @return a mock object created by EasyMock and wrapped by the object
+   *         implementing this method.
+   */
+  Object getDelegate___AndroidMock();
+}
diff --git a/src/com/google/android/testing/mocking/ProcessorLogger.java b/src/com/google/android/testing/mocking/ProcessorLogger.java
new file mode 100644
index 0000000..d2d853c
--- /dev/null
+++ b/src/com/google/android/testing/mocking/ProcessorLogger.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.tools.Diagnostic.Kind;
+
+/**
+ * @author swoodward@google.com (Stephen Woodward)
+ * 
+ */
+class ProcessorLogger {
+  private final OutputStream logFile;
+  private final ProcessingEnvironment processingEnv;
+
+  ProcessorLogger(OutputStream logFile, ProcessingEnvironment processingEnv) {
+    this.logFile = logFile;
+    this.processingEnv = processingEnv;
+  }
+
+  ProcessorLogger(String logFileName, ProcessingEnvironment processingEnv) {
+    this.logFile = openLogFile(logFileName);
+    this.processingEnv = processingEnv;
+  }
+
+  void reportClasspathError(String clazz, Throwable e) {
+    printMessage(Kind.ERROR, "Could not find " + clazz);
+    printMessage(Kind.ERROR, e);
+    printMessage(Kind.NOTE, "Known Classpath: ");
+    URL[] allUrls = ((URLClassLoader) this.getClass().getClassLoader()).getURLs();
+    for (URL url : allUrls) {
+      printMessage(Kind.NOTE, url.toString());
+    }
+  }
+
+  void printMessage(Kind kind, String message) {
+    processingEnv.getMessager().printMessage(kind, message);
+    if (logFile != null) {
+      try {
+        logFile.write((SimpleDateFormat.getDateTimeInstance().format(new Date()) + " - "
+            + kind.toString() + " : " + message + "\n").getBytes());
+      } catch (IOException e) {
+        // That's unfortunate, but not much to do about it.
+        processingEnv.getMessager().printMessage(Kind.WARNING,
+            "IOException logging to file" + e.toString());
+      }
+    }
+  }
+
+  void printMessage(Kind kind, Throwable e) {
+    ByteArrayOutputStream stackTraceByteStream = new ByteArrayOutputStream();
+    PrintStream stackTraceStream = new PrintStream(stackTraceByteStream);
+    e.printStackTrace(stackTraceStream);
+    printMessage(kind, stackTraceByteStream.toString());
+  }
+
+  FileOutputStream openLogFile(String logFileName) {
+    try {
+      if (logFileName != null) {
+        File log = new File(logFileName);
+        if (!log.exists() && log.getParentFile() != null) {
+          log.getParentFile().mkdirs();
+        }
+        return new FileOutputStream(log, true);
+      }
+    } catch (FileNotFoundException e) {
+      printMessage(Kind.WARNING, e);
+    }
+    return null;
+  }
+
+  void close() {
+    if (logFile != null) {
+      try {
+        logFile.close();
+      } catch (IOException e) {
+        // That's ok
+      }
+    }
+  }
+}
diff --git a/src/com/google/android/testing/mocking/SdkVersion.java b/src/com/google/android/testing/mocking/SdkVersion.java
new file mode 100644
index 0000000..ee61707
--- /dev/null
+++ b/src/com/google/android/testing/mocking/SdkVersion.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+
+
+/**
+ * Represents different SDK versions of the Android SDK.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public enum SdkVersion {
+  UNKNOWN("", -1), CUPCAKE("v15", 3), DONUT("v16", 4), ECLAIR_0_1("v201", 6),
+  ECLAIR_MR1("v21", 7), FROYO("v22", 8);
+
+  private static final int SDK_VERSION;
+
+  static {
+    String sdkString = null;
+    int sdkInt;
+    try {
+      Class<?> buildClass = Class.forName("android.os.Build$VERSION");
+      Field sdkField = buildClass.getField("SDK");
+      sdkString = (String) sdkField.get(null);
+      sdkInt = Integer.parseInt(sdkString);
+    } catch (Exception e) {
+      // This will always happen on the desktop side.  No big deal.
+      if (sdkString != null) {
+        // But this is unexpected
+        System.out.println(e.toString());
+        e.printStackTrace();
+      }
+      sdkInt = -1;
+    }
+    SDK_VERSION = sdkInt;
+  }
+
+  private final String prefix;
+  private final String versionName;
+  private final int apiLevel;
+
+  private SdkVersion(String packagePrefix, int apiLevel) {
+    versionName = packagePrefix;
+    prefix = packagePrefix.length() == 0 ? "" : packagePrefix + ".";
+    this.apiLevel = apiLevel;
+  }
+
+  /**
+   * Returns an array of SdkVersion objects.  This is to be favoured over the
+   * {@link #values()} method, since that method will also return the UNKNOWN
+   * SDK version, which is not usually a valid version on which to operate.
+   * 
+   * @return an array of SdkVersion objects.
+   */
+  public static SdkVersion[] getAllVersions() {
+    List<SdkVersion> versions = new ArrayList<SdkVersion>();
+    for (SdkVersion version : values()) {
+      if (!version.equals(UNKNOWN)) {
+        versions.add(version);
+      }
+    }
+    return versions.toArray(new SdkVersion[versions.size()]);
+  }
+
+  public String getVersionName() {
+    return versionName;
+  }
+
+  public String getPackagePrefix() {
+    return prefix;
+  }
+
+  /**
+   * Returns the current SDK version, or UNKNOWN if the version cannot be determined (for instance
+   * if this method is invoked from within a J2SE environment).
+   * @return the current SDK version.
+   */
+  public static SdkVersion getCurrentVersion() {
+    return getVersionFor(SDK_VERSION);
+  }
+
+  static SdkVersion getVersionFor(int apiLevel) {
+    for (SdkVersion version : values()) {
+      if (version.apiLevel == apiLevel) {
+        return version;
+      }
+    }
+    return UNKNOWN;
+  }
+}
diff --git a/src/com/google/android/testing/mocking/UsesMocks.java b/src/com/google/android/testing/mocking/UsesMocks.java
new file mode 100644
index 0000000..55cd1de
--- /dev/null
+++ b/src/com/google/android/testing/mocking/UsesMocks.java
@@ -0,0 +1,33 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation that indicates that a Class should be prepared for Mocking.
+ *
+ * E.g. {@code &#64;UsesMocks(ClassToMock.class)} will indicate that ClassToMock should be prepared
+ * for mocking. Preparation for mocking involves the creation of new classes that will then be
+ * available at runtime on the Dalvik VM (assuming that the Jar file generated by MockGenerator is
+ * added to the APK uploaded to the device/emulator).
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface UsesMocks {
+  Class<?>[] value();
+}
diff --git a/src/com/google/android/testing/mocking/UsesMocksProcessor.java b/src/com/google/android/testing/mocking/UsesMocksProcessor.java
new file mode 100644
index 0000000..0ca5c48
--- /dev/null
+++ b/src/com/google/android/testing/mocking/UsesMocksProcessor.java
@@ -0,0 +1,240 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.JavaFileObject;
+
+
+/**
+ * Annotation Processor to generate the mocks for Android Mock.
+ * 
+ * This processor will automatically create mocks for all classes
+ * specified by {@link UsesMocks} annotations.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+@SupportedAnnotationTypes("com.google.android.testing.mocking.UsesMocks")
+@SupportedSourceVersion(SourceVersion.RELEASE_5)
+@SupportedOptions({
+    UsesMocksProcessor.REGENERATE_FRAMEWORK_MOCKS,
+    UsesMocksProcessor.LOGFILE,
+    UsesMocksProcessor.BIN_DIR
+})
+public class UsesMocksProcessor extends AbstractProcessor {
+  public static final String LOGFILE = "logfile";
+  public static final String REGENERATE_FRAMEWORK_MOCKS = "RegenerateFrameworkMocks";
+  public static final String BIN_DIR = "bin_dir";
+  private AndroidMockGenerator mockGenerator = new AndroidMockGenerator();
+  private AndroidFrameworkMockGenerator frameworkMockGenerator =
+      new AndroidFrameworkMockGenerator();
+  ProcessorLogger logger;
+
+  /**
+   * Main entry point of the processor.  This is called by the Annotation framework.
+   * {@link javax.annotation.processing.AbstractProcessor} for more details.
+   */
+  @Override
+  public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment environment) {
+    try {
+      prepareLogger();
+      List<Class<?>> classesToMock = getClassesToMock(environment);
+      Set<GeneratedClassFile> mockedClassesSet = getMocksFor(classesToMock);
+      writeMocks(mockedClassesSet);
+    } catch (Exception e) {
+      logger.printMessage(Kind.ERROR, e);
+    } finally {
+      logger.close();
+    }
+    return false;
+  }
+
+  /**
+   * Returns a Set of GeneratedClassFile objects which represent all of the classes to be mocked.
+   * 
+   * @param classesToMock the list of classes which need to be mocked.
+   * @return a set of mock support classes to support the mocking of all the classes specified in
+   *         {@literal classesToMock}.
+   */
+  private Set<GeneratedClassFile> getMocksFor(List<Class<?>> classesToMock) throws IOException,
+      CannotCompileException {
+    logger.printMessage(Kind.NOTE, "Found " + classesToMock.size() + " classes to mock");
+    boolean regenerateFrameworkMocks = processingEnv.getOptions().get(
+        REGENERATE_FRAMEWORK_MOCKS) != null;
+    if (regenerateFrameworkMocks) {
+      logger.printMessage(Kind.NOTE, "Regenerating Framework Mocks on Request");
+    }
+    Set<GeneratedClassFile> mockedClassesSet =
+        getClassMocks(classesToMock, regenerateFrameworkMocks);
+    logger.printMessage(Kind.NOTE, "Found " + mockedClassesSet.size()
+        + " mocked classes to save");
+    return mockedClassesSet;
+  }
+
+  /**
+   * @param environment the environment for this round of processing as provided to the main
+   *        {@link #process(Set, RoundEnvironment)} method.
+   * @return a List of Class objects for the classes that need to be mocked.
+   */
+  private List<Class<?>> getClassesToMock(RoundEnvironment environment) {
+    logger.printMessage(Kind.NOTE, "Start Processing Annotations");
+    List<Class<?>> classesToMock = new ArrayList<Class<?>>();
+    classesToMock.addAll(
+        findClassesToMock(environment.getElementsAnnotatedWith(UsesMocks.class)));
+    return classesToMock;
+  }
+
+  private void prepareLogger() {
+    if (logger == null) {
+      logger = new ProcessorLogger(processingEnv.getOptions().get(LOGFILE), processingEnv);
+    }
+  }
+
+  /**
+   * Finds all of the classes that should be mocked, based on {@link UsesMocks} annotations
+   * in the various source files being compiled.
+   * 
+   * @param annotatedElements a Set of all elements holding {@link UsesMocks} annotations.
+   * @return all of the classes that should be mocked.
+   */
+  List<Class<?>> findClassesToMock(Set<? extends Element> annotatedElements) {
+    logger.printMessage(Kind.NOTE, "Processing " + annotatedElements);
+    List<Class<?>> classList = new ArrayList<Class<?>>();
+    for (Element annotation : annotatedElements) {
+      List<? extends AnnotationMirror> mirrors = annotation.getAnnotationMirrors();
+      for (AnnotationMirror mirror : mirrors) {
+        if (mirror.getAnnotationType().toString().equals(UsesMocks.class.getName())) {
+          for (AnnotationValue annotationValue : mirror.getElementValues().values()) {
+            for (Object classFileName : (Iterable<?>) annotationValue.getValue()) {
+              String className = classFileName.toString();
+              if (className.endsWith(".class")) {
+                className = className.substring(0, className.length() - 6);
+              }
+              logger.printMessage(Kind.NOTE, "Adding Class to Mocking List: " + className);
+              try {
+                classList.add(Class.forName(className, false, getClass().getClassLoader()));
+              } catch (ClassNotFoundException e) {
+                logger.reportClasspathError(className, e);
+              }
+            }
+          }
+        }
+      }
+    }
+    return classList;
+  }
+
+  /**
+   * Gets a set of GeneratedClassFiles to represent all of the support classes required to
+   * mock the List of classes provided in {@code classesToMock}.
+   * @param classesToMock the list of classes to be mocked.
+   * @param regenerateFrameworkMocks if true, then mocks for the framework classes will be created
+   *        instead of pulled from the existing set of framework support classes.
+   * @return a Set of {@link GeneratedClassFile} for all of the mocked classes.
+   */
+  Set<GeneratedClassFile> getClassMocks(List<Class<?>> classesToMock,
+      boolean regenerateFrameworkMocks) throws IOException, CannotCompileException {
+    Set<GeneratedClassFile> mockedClassesSet = new HashSet<GeneratedClassFile>();
+    for (Class<?> clazz : classesToMock) {
+      try {
+        logger.printMessage(Kind.NOTE, "Mocking " + clazz);
+        if (!AndroidMock.isAndroidClass(clazz) || regenerateFrameworkMocks) {
+          mockedClassesSet.addAll(getAndroidMockGenerator().createMocksForClass(clazz));
+        } else {
+          mockedClassesSet.addAll(getAndroidFrameworkMockGenerator().getMocksForClass(clazz));
+        }
+      } catch (ClassNotFoundException e) {
+        logger.reportClasspathError(clazz.getName(), e);
+      } catch (NoClassDefFoundError e) {
+        logger.reportClasspathError(clazz.getName(), e);
+      }
+    }
+    return mockedClassesSet;
+  }
+
+  private AndroidFrameworkMockGenerator getAndroidFrameworkMockGenerator() {
+    return frameworkMockGenerator;
+  }
+
+  /**
+   * Writes the provided mocks from {@code mockedClassesSet} to the bin folder alongside the
+   * .class files being generated by the javac call which invoked this annotation processor.
+   * In Eclipse, additional information is needed as the Eclipse annotation processor framework
+   * is missing key functionality required by this method.  Instead the classes are saved using
+   * a FileOutputStream and the -Abin_dir processor option must be set.
+   * @param mockedClassesSet the set of mocks to be saved.
+   */
+  void writeMocks(Set<GeneratedClassFile> mockedClassesSet) {
+    for (GeneratedClassFile clazz : mockedClassesSet) {
+      OutputStream classFileStream;
+      try {
+        logger.printMessage(Kind.NOTE, "Saving " + clazz.getClassName());
+        JavaFileObject classFile = processingEnv.getFiler().createClassFile(clazz.getClassName());
+        classFileStream = classFile.openOutputStream();
+        classFileStream.write(clazz.getContents());
+        classFileStream.close();
+      } catch (IOException e) {
+        logger.printMessage(Kind.ERROR, "Internal Error saving mock: " + clazz.getClassName());
+        logger.printMessage(Kind.ERROR, e);
+      } catch (UnsupportedOperationException e) {
+        // Eclipse annotation processing doesn't support class creation.
+        logger.printMessage(Kind.NOTE, "Saving via Eclipse " + clazz.getClassName());
+        saveMocksEclipse(clazz, processingEnv.getOptions().get(BIN_DIR).toString().trim());
+      }
+    }
+    logger.printMessage(Kind.NOTE, "Finished Processing Mocks");
+  }
+
+  /**
+   * Workaround to save the mocks for Eclipse's annotation processing framework which doesn't
+   * support the JavaFileObject object.
+   * @param clazz the class to save.
+   * @param outputFolderName the output folder where the class will be saved.
+   */
+  private void saveMocksEclipse(GeneratedClassFile clazz, String outputFolderName) {
+    try {
+      FileUtils.saveClassToFolder(clazz, outputFolderName);
+    } catch (FileNotFoundException e) {
+      logger.printMessage(Kind.ERROR, e);
+    } catch (IOException e) {
+      logger.printMessage(Kind.ERROR, e);
+    }
+  }
+
+  private AndroidMockGenerator getAndroidMockGenerator() {
+    return mockGenerator;
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java b/tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java
new file mode 100644
index 0000000..813063f
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.NotFoundException;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Vector;
+import java.util.jar.JarEntry;
+
+/**
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class AndroidFrameworkMockGeneratorTest extends TestCase {
+  private void cleanupGeneratedClasses(CtClass... classes) {
+    for (CtClass clazz : classes) {
+      clazz.detach();
+    }
+  }
+
+  private Collection<JarEntry> getMockJarEntries() {
+    JarEntry firstEntry = new JarEntry("java/lang/Object.class");
+    JarEntry secondEntry = new JarEntry(
+        "com/google/android/testing/mocking/AndroidFrameworkMockGeneratorTest$Inner.class");
+    List<JarEntry> entryList = new ArrayList<JarEntry>();
+    entryList.add(firstEntry);
+    entryList.add(secondEntry);
+    return entryList;
+  }
+
+  private <T> void assertUnorderedContentsSame(Iterable<T> expected, Iterable<T> actual) {
+    List<T> missingItems = new ArrayList<T>();
+    List<T> extraItems = new ArrayList<T>();
+    for (T item : expected) {
+      missingItems.add(item);
+    }
+    for (T item : actual) {
+      missingItems.remove(item);
+      extraItems.add(item);
+    }
+    for (T item : expected) {
+      extraItems.remove(item);
+    }
+    if (missingItems.size() + extraItems.size() != 0) {
+      String errorMessage =
+          "Contents were different. Missing: " + Arrays.toString(missingItems.toArray())
+              + " Extra: " + Arrays.toString(extraItems.toArray());
+      fail(errorMessage);
+    }
+  }
+
+  private List<String> getClassNames(List<GeneratedClassFile> classes) {
+    List<String> classNames = new ArrayList<String>();
+    for (GeneratedClassFile clazz : classes) {
+      classNames.add(clazz.getClassName());
+    }
+    return classNames;
+  }
+
+  private AndroidFrameworkMockGenerator getMockGenerator() {
+    return new AndroidFrameworkMockGenerator();
+  }
+
+  public void testCreateMockForClass() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidFrameworkMockGenerator mockGenerator = getMockGenerator();
+    for (SdkVersion version : SdkVersion.getAllVersions()) {
+      List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Object.class, version);
+  
+      List<String> expectedNames = new ArrayList<String>();
+      expectedNames.addAll(Arrays.asList(new String[] {
+          version.getPackagePrefix() + "genmocks.java.lang.ObjectDelegateSubclass",
+          version.getPackagePrefix() + "genmocks.java.lang.ObjectDelegateInterface"}));
+      List<String> actualNames = getClassNames(classes);
+      assertUnorderedContentsSame(expectedNames, actualNames);
+    }
+  }
+
+  public void testGetClassList() throws ClassNotFoundException {
+    Collection<JarEntry> jarEntries = getMockJarEntries();
+    List<String> expectedClassNames =
+        new ArrayList<String>(Arrays.asList(new String[] {
+            "java.lang.Object",
+            "com.google.android.testing.mocking.AndroidFrameworkMockGeneratorTest$Inner"}));
+    List<Class<?>> list = getMockGenerator().getClassList(jarEntries);
+    assertEquals(expectedClassNames.size(), list.size());
+    for (Class<?> clazz : list) {
+      assertTrue(clazz.getName(), expectedClassNames.contains(clazz.getName()));
+    }
+  }
+
+  public void testIsClassFile() {
+    assertTrue(getMockGenerator().jarEntryIsClassFile(new JarEntry("something.class")));
+    assertTrue(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.class")));
+    assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.clas")));
+    assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar.class ")));
+    assertFalse(getMockGenerator().jarEntryIsClassFile(new JarEntry("/Foo/Bar")));
+  }
+
+  public void testGetJarFileNameForVersion() {
+    for (SdkVersion version : SdkVersion.getAllVersions()) {
+      getMockGenerator();
+      assertEquals("lib/android/android_" + version.getVersionName() + ".jar",
+          AndroidFrameworkMockGenerator.getJarFileNameForVersion(version));
+    }
+  }
+
+  public void testGetMocksForClass() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<CtClass> createdClasses = new ArrayList<CtClass>();
+    AndroidFrameworkMockGenerator mockGenerator = getMockGenerator();
+    for (SdkVersion version : SdkVersion.getAllVersions()) {
+      List<GeneratedClassFile> createdMocks = mockGenerator.createMocksForClass(
+          Vector.class, version);
+      for (GeneratedClassFile mock : createdMocks) {
+        CtClass ctClass = ClassPool.getDefault().get(mock.getClassName());
+        createdClasses.add(ctClass);
+        ctClass.toClass();
+      }
+    }
+    List<GeneratedClassFile> mocks = mockGenerator.getMocksForClass(Vector.class);
+    String[] expectedClassNames = new String[] {
+        "v15.genmocks.java.util.VectorDelegateSubclass",
+        "v15.genmocks.java.util.VectorDelegateInterface",
+        "v16.genmocks.java.util.VectorDelegateSubclass",
+        "v16.genmocks.java.util.VectorDelegateInterface",
+        "v201.genmocks.java.util.VectorDelegateSubclass",
+        "v201.genmocks.java.util.VectorDelegateInterface",
+        "v21.genmocks.java.util.VectorDelegateSubclass",
+        "v21.genmocks.java.util.VectorDelegateInterface",
+        "v22.genmocks.java.util.VectorDelegateSubclass",
+        "v22.genmocks.java.util.VectorDelegateInterface"
+    };
+    assertEquals(expectedClassNames.length, mocks.size());
+    for (int i = 0; i < mocks.size(); ++i) {
+      assertEquals(expectedClassNames[i], mocks.get(i).getClassName());
+    }
+    cleanupGeneratedClasses(createdClasses.toArray(new CtClass[0]));
+  }
+
+  class Inner {
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java b/tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java
new file mode 100644
index 0000000..ef36b24
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/AndroidMockGeneratorTest.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+
+/**
+ * Tests for the AndroidMockGenerator class.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class AndroidMockGeneratorTest extends TestCase {
+  private AndroidMockGenerator getAndroidMockGenerator() {
+    return new AndroidMockGenerator();
+  }
+
+  private NoFileAndroidMockGenerator getNoFileMockGenerator() {
+    return new NoFileAndroidMockGenerator();
+  }
+
+  private void cleanupGeneratedClasses(CtClass... classes) {
+    for (CtClass clazz : classes) {
+      clazz.detach();
+    }
+  }
+
+  private <T> void assertUnorderedContentsSame(Iterable<T> expected, Iterable<T> actual) {
+    List<T> missingItems = new ArrayList<T>();
+    List<T> extraItems = new ArrayList<T>();
+    for (T item : expected) {
+      missingItems.add(item);
+    }
+    for (T item : actual) {
+      missingItems.remove(item);
+      extraItems.add(item);
+    }
+    for (T item : expected) {
+      extraItems.remove(item);
+    }
+    if (missingItems.size() + extraItems.size() != 0) {
+      String errorMessage =
+          "Contents were different. Missing: " + Arrays.toString(missingItems.toArray())
+              + " Extra: " + Arrays.toString(extraItems.toArray());
+      fail(errorMessage);
+    }
+  }
+
+  private List<String> getExpectedNamesForNumberClass() {
+    return getExpectedNamesForNumberClass(false);
+  }
+
+  private List<String> getExpectedNamesForObjectClass() {
+    List<String> expectedNames = new ArrayList<String>();
+    expectedNames.addAll(Arrays.asList(new String[] {"clone", "finalize"}));
+    return expectedNames;
+  }
+
+  private List<String> getExpectedNamesForNumberClass(boolean includeDelegateMethods) {
+    List<String> expectedNames = getExpectedNamesForObjectClass();
+    expectedNames.addAll(Arrays.asList(new String[] {"byteValue", "doubleValue", "floatValue",
+        "intValue", "longValue", "shortValue"}));
+    if (includeDelegateMethods) {
+      expectedNames.addAll(Arrays.asList(new String[] {"getDelegate___AndroidMock",
+          "setDelegate___AndroidMock"}));
+    }
+    return expectedNames;
+  }
+
+  private List<String> getExpectedNamesForBigIntegerClass() {
+    List<String> expectedNames = getExpectedNamesForNumberClass();
+    expectedNames.addAll(Arrays.asList(new String[] {"abs", "add", "and", "andNot", "bitCount",
+        "bitLength", "clearBit", "compareTo", "divide", "divideAndRemainder", "flipBit", "gcd",
+        "getLowestSetBit", "isProbablePrime", "max", "min", "mod", "modInverse", "modPow",
+        "multiply", "negate", "nextProbablePrime", "not", "or", "pow", "remainder", "setBit",
+        "shiftLeft", "shiftRight", "signum", "subtract", "testBit", "toByteArray", "toString",
+        "xor"}));
+    return expectedNames;
+  }
+
+  private List<String> getMethodNames(CtMethod[] methods) {
+    List<String> methodNames = new ArrayList<String>();
+    for (CtMethod method : methods) {
+      methodNames.add(method.getName());
+    }
+    return methodNames;
+  }
+
+  private List<String> getClassNames(List<GeneratedClassFile> classes) {
+    List<String> classNames = new ArrayList<String>();
+    for (GeneratedClassFile clazz : classes) {
+      classNames.add(clazz.getClassName());
+    }
+    return classNames;
+  }
+
+  private List<String> getExpectedSignaturesForBigIntegerClass() {
+    List<String> expectedNames = new ArrayList<String>();
+    expectedNames.addAll(Arrays.asList(new String[] {
+        "public int java.math.BigInteger.getLowestSetBit()",
+        "public java.math.BigInteger java.math.BigInteger.abs()",
+        "protected void java.lang.Object.finalize() throws java.lang.Throwable",
+        "public java.math.BigInteger java.math.BigInteger.modPow(java.math.BigInteger,"
+            + "java.math.BigInteger)",
+        "protected native java.lang.Object java.lang.Object.clone() throws "
+            + "java.lang.CloneNotSupportedException",
+        "public java.math.BigInteger java.math.BigInteger.setBit(int)",
+        "public java.math.BigInteger java.math.BigInteger.shiftRight(int)",
+        "public int java.math.BigInteger.bitLength()",
+        "public java.math.BigInteger java.math.BigInteger.not()",
+        "public java.math.BigInteger java.math.BigInteger.subtract(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.flipBit(int)",
+        "public boolean java.math.BigInteger.isProbablePrime(int)",
+        "public java.math.BigInteger java.math.BigInteger.add(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.modInverse(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.clearBit(int)",
+        "public java.math.BigInteger java.math.BigInteger.multiply(java.math.BigInteger)",
+        "public byte java.lang.Number.byteValue()",
+        "public java.math.BigInteger java.math.BigInteger.gcd(java.math.BigInteger)",
+        "public float java.math.BigInteger.floatValue()",
+        "public java.lang.String java.math.BigInteger.toString(int)",
+        "public java.math.BigInteger java.math.BigInteger.min(java.math.BigInteger)",
+        "public int java.math.BigInteger.intValue()",
+        "public java.math.BigInteger java.math.BigInteger.or(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.remainder(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.divide(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.xor(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.and(java.math.BigInteger)",
+        "public int java.math.BigInteger.signum()",
+        "public java.math.BigInteger[] java.math.BigInteger.divideAndRemainder("
+            + "java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.max(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.shiftLeft(int)",
+        "public double java.math.BigInteger.doubleValue()",
+        "public java.math.BigInteger java.math.BigInteger.pow(int)",
+        "public short java.lang.Number.shortValue()",
+        "public java.math.BigInteger java.math.BigInteger.andNot(java.math.BigInteger)",
+        "public byte[] java.math.BigInteger.toByteArray()",
+        "public java.math.BigInteger java.math.BigInteger.negate()",
+        "public int java.math.BigInteger.compareTo(java.math.BigInteger)",
+        "public boolean java.math.BigInteger.testBit(int)",
+        "public int java.math.BigInteger.bitCount()",
+        "public long java.math.BigInteger.longValue()",
+        "public java.math.BigInteger java.math.BigInteger.mod(java.math.BigInteger)",
+        "public java.math.BigInteger java.math.BigInteger.nextProbablePrime()",
+        }));
+    return expectedNames;
+  }
+
+  private List<String> getMethodSignatures(Method[] methods) {
+    List<String> methodSignatures = new ArrayList<String>();
+    for (Method method : methods) {
+      if (getAndroidMockGenerator().isMockable(method)) {
+        methodSignatures.add(method.toGenericString());
+      }
+    }
+    return methodSignatures;
+  }
+
+  public void testIsSupportedType() {
+    Class<?>[] unsupportedClasses =
+        new Class[] {ClassIsAnnotation.class, ClassIsEnum.class, ClassIsFinal.class,
+            ClassIsInterface.class};
+    Class<?>[] supportedClasses = new Class[] {Object.class};
+
+    for (Class<?> clazz : unsupportedClasses) {
+      assertFalse(getAndroidMockGenerator().classIsSupportedType(clazz));
+    }
+    for (Class<?> clazz : supportedClasses) {
+      assertTrue(getAndroidMockGenerator().classIsSupportedType(clazz));
+    }
+  }
+
+  public void testGetDelegateFieldName() {
+    assertEquals("delegateMockObject", getAndroidMockGenerator().getDelegateFieldName());
+  }
+
+  public void testGetInterfaceMethodSource() throws SecurityException, NoSuchMethodException {
+    Method method = Object.class.getMethod("equals", Object.class);
+    assertEquals("public boolean equals(java.lang.Object arg0);", getAndroidMockGenerator()
+        .getInterfaceMethodSource(method));
+  }
+
+  public void testGetInterfaceMethodSourceMultipleExceptions() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Class.class.getDeclaredMethod("newInstance");
+    assertEquals("public java.lang.Object newInstance() throws java.lang.InstantiationException,"
+        + "java.lang.IllegalAccessException;", getAndroidMockGenerator().getInterfaceMethodSource(
+        method));
+  }
+
+  public void testGetInterfaceMethodSourceProtectedMethod() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Object.class.getDeclaredMethod("finalize");
+    assertEquals("public void finalize() throws java.lang.Throwable;", getAndroidMockGenerator()
+        .getInterfaceMethodSource(method));
+  }
+
+  public void testGetInterfaceMethodSourceNoParams() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Object.class.getMethod("toString");
+    assertEquals("public java.lang.String toString();", getAndroidMockGenerator()
+        .getInterfaceMethodSource(method));
+  }
+
+  public void testGetInterfaceMethodSourceVoidReturn() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Thread.class.getMethod("run");
+    assertEquals("public void run();", getAndroidMockGenerator().getInterfaceMethodSource(method));
+  }
+
+  public void testGetInterfaceMethodSourceFinal() throws SecurityException, NoSuchMethodException {
+    Method method = Object.class.getMethod("notify");
+    try {
+      getAndroidMockGenerator().getInterfaceMethodSource(method);
+      fail("Exception not thrown on a final method");
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+
+  public void testGetInterfaceMethodSourceStatic() throws SecurityException, NoSuchMethodException {
+    Method method = Thread.class.getMethod("currentThread");
+    try {
+      getAndroidMockGenerator().getInterfaceMethodSource(method);
+      fail("Exception not thrown on a static method");
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+
+  public void testGetInterfaceName() {
+    AndroidMockGenerator r = getAndroidMockGenerator();
+    assertEquals("genmocks.java.lang.ObjectDelegateInterface",
+        FileUtils.getInterfaceNameFor(Object.class, SdkVersion.UNKNOWN));
+  }
+
+  public void testGetSubclassName() {
+    AndroidMockGenerator r = getAndroidMockGenerator();
+    assertEquals("genmocks.java.lang.ObjectDelegateSubclass",
+        FileUtils.getSubclassNameFor(Object.class, SdkVersion.UNKNOWN));
+  }
+
+  public void testGetDelegateMethodSource() throws SecurityException, NoSuchMethodException {
+    Method method = Object.class.getMethod("equals", Object.class);
+    assertEquals("public boolean equals(java.lang.Object arg0){if(this.delegateMockObject==null){"
+        + "return false;}return this.delegateMockObject.equals(arg0);}", getAndroidMockGenerator()
+        .getDelegateMethodSource(method));
+  }
+
+  public void testGetDelegateMethodSourceAllTypes() throws SecurityException,
+      NoSuchMethodException {
+    String[] returnTypes =
+        new String[] {"boolean", "byte", "short", "int", "long", "char", "float", "double"};
+    String[] castTypes =
+        new String[] {"false", "(byte)0", "(short)0", "(int)0", "(long)0", "(char)0", "(float)0",
+            "(double)0"};
+    for (int i = 0; i < returnTypes.length; ++i) {
+      Method method = AllTypes.class.getMethod(returnTypes[i] + "Foo");
+      assertEquals("public " + returnTypes[i] + " " + returnTypes[i]
+          + "Foo(){if(this.delegateMockObject==null){return " + castTypes[i]
+          + ";}return this.delegateMockObject." + returnTypes[i] + "Foo();}",
+          getAndroidMockGenerator().getDelegateMethodSource(method));
+    }
+    Method method = AllTypes.class.getMethod("objectFoo");
+    assertEquals("public java.lang.Object objectFoo(){if(this.delegateMockObject==null){return "
+        + "null;}return this.delegateMockObject.objectFoo();}", getAndroidMockGenerator()
+        .getDelegateMethodSource(method));
+    method = AllTypes.class.getMethod("voidFoo");
+    assertEquals("public void voidFoo(){if(this.delegateMockObject==null){return ;"
+        + "}this.delegateMockObject.voidFoo();}", getAndroidMockGenerator()
+        .getDelegateMethodSource(method));
+  }
+
+  private class AllTypes {
+    @SuppressWarnings("unused")
+    public void voidFoo() {
+    }
+
+    @SuppressWarnings("unused")
+    public boolean booleanFoo() {
+      return false;
+    }
+
+    @SuppressWarnings("unused")
+    public byte byteFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public short shortFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public int intFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public long longFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public char charFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public float floatFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public double doubleFoo() {
+      return 0;
+    }
+
+    @SuppressWarnings("unused")
+    public Object objectFoo() {
+      return null;
+    }
+  }
+
+  public void testGetDelegateMethodSourceMultipleExceptions() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Class.class.getDeclaredMethod("newInstance");
+    assertEquals(
+        "public java.lang.Object newInstance() throws java.lang.InstantiationException,"
+            + "java.lang.IllegalAccessException{if(this.delegateMockObject==null){return null;}"
+            + "return this.delegateMockObject.newInstance();}", getAndroidMockGenerator()
+            .getDelegateMethodSource(method));
+  }
+
+  public void testGetDelegateMethodSourceProtectedMethod() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Object.class.getDeclaredMethod("finalize");
+    assertEquals("public void finalize() throws java.lang.Throwable{if(this.delegateMockObject=="
+        + "null){return ;}this.delegateMockObject.finalize();}", getAndroidMockGenerator()
+        .getDelegateMethodSource(method));
+  }
+
+  public void testGetDelegateMethodSourceMultiParams() throws SecurityException,
+      NoSuchMethodException {
+    Method method =
+        String.class.getMethod("getChars", Integer.TYPE, Integer.TYPE, char[].class, Integer.TYPE);
+    assertEquals(
+        "public void getChars(int arg0,int arg1,char[] arg2,int arg3){if(this."
+            + "delegateMockObject==null){return ;}this.delegateMockObject.getChars(arg0,arg1,arg2,"
+            + "arg3);}", getAndroidMockGenerator().getDelegateMethodSource(method));
+  }
+
+  public void testGetDelegateMethodSourceNoParams() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Object.class.getMethod("toString");
+    assertEquals(
+        "public java.lang.String toString(){if(this.delegateMockObject==null){return null;"
+            + "}return this.delegateMockObject.toString();}", getAndroidMockGenerator()
+            .getDelegateMethodSource(method));
+  }
+
+  public void testGetDelegateMethodSourceVoidReturn() throws SecurityException,
+      NoSuchMethodException {
+    Method method = Thread.class.getMethod("run");
+    assertEquals("public void run(){if(this.delegateMockObject==null){return ;}this."
+        + "delegateMockObject.run();}", getAndroidMockGenerator().getDelegateMethodSource(method));
+  }
+
+  public void testGetDelegateMethodSourceFinal() throws SecurityException, NoSuchMethodException {
+    Method method = Object.class.getMethod("notify");
+    try {
+      getAndroidMockGenerator().getDelegateMethodSource(method);
+      fail("Exception not thrown on a final method");
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+
+  public void testGetDelegateMethodSourceStatic() throws SecurityException, NoSuchMethodException {
+    Method method = Thread.class.getMethod("currentThread");
+    try {
+      getAndroidMockGenerator().getDelegateMethodSource(method);
+      fail("Exception not thrown on a static method");
+    } catch (UnsupportedOperationException e) {
+      // expected
+    }
+  }
+
+  public void testGenerateEmptySubclass() throws ClassNotFoundException, NotFoundException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(String.class, SdkVersion.UNKNOWN);
+    CtClass generatedClass = getAndroidMockGenerator().generateSkeletalClass(
+        String.class, generatedInterface, SdkVersion.UNKNOWN);
+
+    assertEquals("genmocks.java.lang", generatedClass.getPackageName());
+    assertEquals("StringDelegateSubclass", generatedClass.getSimpleName());
+    assertEquals("java.lang.String", generatedClass.getSuperclass().getName());
+    cleanupGeneratedClasses(generatedInterface, generatedClass);
+  }
+
+  public void testAddMethods() throws ClassNotFoundException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN);
+    CtClass generatedClass =
+        mockGenerator.generateSkeletalClass(Number.class, generatedInterface, SdkVersion.UNKNOWN);
+
+    mockGenerator.addMethods(Number.class, generatedClass);
+
+    List<String> expectedNames = getExpectedNamesForNumberClass();
+    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface, generatedClass);
+  }
+
+  public void testAddMethodsObjectClass() throws ClassNotFoundException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(Object.class, SdkVersion.UNKNOWN);
+    CtClass generatedClass =
+        mockGenerator.generateSkeletalClass(Object.class, generatedInterface, SdkVersion.UNKNOWN);
+
+    mockGenerator.addMethods(Object.class, generatedClass);
+
+    List<String> expectedNames = getExpectedNamesForObjectClass();
+    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface, generatedClass);
+  }
+
+  public void testAddMethodsUsesSuperclass() throws ClassNotFoundException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(
+        BigInteger.class, SdkVersion.UNKNOWN);
+    CtClass generatedClass = mockGenerator.generateSkeletalClass(
+        BigInteger.class, generatedInterface, SdkVersion.UNKNOWN);
+
+    mockGenerator.addMethods(BigInteger.class, generatedClass);
+
+    List<String> expectedNames = getExpectedNamesForBigIntegerClass();
+    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface, generatedClass);
+  }
+
+  public void testGetAllMethods() throws ClassNotFoundException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(
+        BigInteger.class, SdkVersion.UNKNOWN);
+    CtClass generatedClass = mockGenerator.generateSkeletalClass(
+        BigInteger.class, generatedInterface, SdkVersion.UNKNOWN);
+
+    Method[] methods = mockGenerator.getAllMethods(BigInteger.class);
+
+    List<String> expectedNames = getExpectedSignaturesForBigIntegerClass();
+    List<String> actualNames = getMethodSignatures(methods);
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface, generatedClass);
+  }
+
+  public void testGenerateInterface() {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN);
+
+    List<String> expectedNames = getExpectedNamesForNumberClass();
+    List<String> actualNames = getMethodNames(generatedInterface.getDeclaredMethods());
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface);
+  }
+
+  public void testAddInterfaceMethods() {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = AndroidMockGenerator.getClassPool().makeInterface("testInterface");
+
+    mockGenerator.addInterfaceMethods(Number.class, generatedInterface);
+
+    List<String> expectedNames = getExpectedNamesForNumberClass();
+    List<String> actualNames = getMethodNames(generatedInterface.getDeclaredMethods());
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface);
+  }
+
+  public void testGenerateSubclass() throws ClassNotFoundException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(Number.class, SdkVersion.UNKNOWN);
+
+    CtClass generatedClass =
+        mockGenerator.generateSubClass(Number.class, generatedInterface, SdkVersion.UNKNOWN);
+
+    List<String> expectedNames = getExpectedNamesForNumberClass(true);
+    List<String> actualNames = getMethodNames(generatedClass.getDeclaredMethods());
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(generatedInterface, generatedClass);
+  }
+
+  public void testCreateMockForClass() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    NoFileAndroidMockGenerator mockGenerator = getNoFileMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Object.class);
+
+    List<String> expectedNames = new ArrayList<String>();
+    String subclassName = "genmocks.java.lang.ObjectDelegateSubclass";
+    String interfaceName = "genmocks.java.lang.ObjectDelegateInterface";
+    expectedNames.addAll(Arrays.asList(new String[] {subclassName,
+        interfaceName}));
+    List<String> actualNames = getClassNames(classes);
+    assertUnorderedContentsSame(expectedNames, actualNames);
+    cleanupGeneratedClasses(
+        ClassPool.getDefault().get(subclassName),
+        ClassPool.getDefault().get(interfaceName));
+  }
+
+  public void testGetSetDelegateMethodSource() {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    CtClass generatedInterface = mockGenerator.generateInterface(Object.class, SdkVersion.UNKNOWN);
+    String expectedSource =
+        "public void setDelegate___AndroidMock(genmocks.java.lang.ObjectDelegateInterface obj) {"
+            + " this.delegateMockObject = obj;}";
+
+    assertEquals(expectedSource, mockGenerator.getSetDelegateMethodSource(generatedInterface));
+  }
+
+  public void testIsForbiddenMethod() throws SecurityException, NoSuchMethodException {
+    Method[] forbiddenMethods =
+        new Method[] {Object.class.getMethod("equals", Object.class),
+            Object.class.getMethod("toString"), Object.class.getMethod("hashCode")};
+    Method[] allowedMethods = new Method[] {BigInteger.class.getMethod("toString", Integer.TYPE)};
+    for (Method method : forbiddenMethods) {
+      assertTrue(getAndroidMockGenerator().isForbiddenMethod(method));
+    }
+    for (Method method : allowedMethods) {
+      assertFalse(getAndroidMockGenerator().isForbiddenMethod(method));
+    }
+  }
+
+  /**
+   * Support test class for capturing the names of files that would have been
+   * saved to a jar file.
+   * 
+   * @author swoodward@google.com (Stephen Woodward)
+   */
+  class NoFileAndroidMockGenerator extends AndroidMockGenerator {
+    List<CtClass> savedClasses = new ArrayList<CtClass>();
+
+    @Override
+    void saveCtClass(CtClass clazz) {
+      savedClasses.add(clazz);
+    }
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/AndroidMockTest.java b/tests/com/google/android/testing/mocking/AndroidMockTest.java
new file mode 100644
index 0000000..56fcbb3
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/AndroidMockTest.java
@@ -0,0 +1,927 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.Modifier;
+import javassist.NotFoundException;
+import javassist.expr.ExprEditor;
+import javassist.expr.MethodCall;
+
+import junit.framework.TestCase;
+
+import org.easymock.Capture;
+import org.easymock.IAnswer;
+import org.easymock.LogicalOperator;
+import org.easymock.internal.matchers.Equals;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInput;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.SimpleTimeZone;
+import java.util.Vector;
+
+
+/**
+ * Tests for the AndroidMock class.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class AndroidMockTest extends TestCase {
+  private List<String> notForwardedMethods =
+      new ArrayList<String>(Arrays.asList(new String[] {
+          "com.google.android.testing.mocking.AndroidMock.getInterfaceFor(java.lang.Class)",
+          "com.google.android.testing.mocking.AndroidMock.getSubclassNameFor(java.lang.Class)",
+          "com.google.android.testing.mocking.AndroidMock.getSubclassFor(java.lang.Class,"
+              + "java.lang.Class,java.lang.Object)",
+          "com.google.android.testing.mocking.AndroidMock.getInterfaceNameFor(java.lang.Class)",
+          "com.google.android.testing.mocking.AndroidMock.createStrictMock("
+              + "java.lang.Class,java.lang.Object[])",
+          "com.google.android.testing.mocking.AndroidMock.createStrictMock("
+              + "java.lang.String,java.lang.Class,java.lang.Object[])",
+          "com.google.android.testing.mocking.AndroidMock.createMock("
+              + "java.lang.Class,java.lang.Object[])",
+          "com.google.android.testing.mocking.AndroidMock.createMock("
+              + "java.lang.String,java.lang.Class,java.lang.Object[])",
+          "com.google.android.testing.mocking.AndroidMock.createNiceMock("
+              + "java.lang.Class,java.lang.Object[])",
+          "com.google.android.testing.mocking.AndroidMock.createNiceMock("
+              + "java.lang.String,java.lang.Class,java.lang.Object[])"}));
+
+  private CtMethod[] getForwardedMethods() throws NotFoundException {
+    List<CtMethod> methods =
+        new ArrayList<CtMethod>(Arrays.asList(getAndroidMockCtClass().getDeclaredMethods()));
+    // Get a copy for safe removal of elements during iteration.
+    for (CtMethod method : Arrays.asList(methods.toArray(new CtMethod[0]))) {
+      if (notForwardedMethods.contains(method.getLongName())
+          || !Modifier.isPublic(method.getModifiers())) {
+        methods.remove(method);
+      }
+    }
+    return methods.toArray(new CtMethod[0]);
+  }
+
+  private CtClass getAndroidMockCtClass() throws NotFoundException {
+    return ClassPool.getDefault().get("com.google.android.testing.mocking.AndroidMock");
+  }
+
+  private void compileClasses(List<GeneratedClassFile> mockClasses) throws NotFoundException {
+    for (GeneratedClassFile clazz : mockClasses) {
+      CtClass ctClass;
+      ctClass = ClassPool.getDefault().get(clazz.getClassName());
+      try {
+        ctClass.toClass();
+      } catch (CannotCompileException e) {
+        // Just ignore -- this will happen for every class used in more than one test.
+      }
+    }
+  }
+
+  public void testIsUnboxableToPrimitiveAllPrimitives() {
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Integer.TYPE, new Integer(42), true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Long.TYPE, new Long(42L), true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Short.TYPE, new Short((short) 42), true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Byte.TYPE, new Byte((byte) 42), true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Boolean.TYPE, Boolean.TRUE, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Float.TYPE, new Float(42.0f), true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Double.TYPE, new Double(42.0), true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Character.TYPE, new Character('a'), true));
+
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Integer.TYPE, 42, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Long.TYPE, 42L, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Short.TYPE, (short) 42, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Byte.TYPE, (byte) 42, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Boolean.TYPE, true, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Float.TYPE, 42.0f, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Double.TYPE, 42.0, true));
+    assertTrue(AndroidMock.isUnboxableToPrimitive(Character.TYPE, 'a', true));
+  }
+
+  public void testIsUnboxableToPrimitiveIsObject() {
+    assertFalse(AndroidMock.isUnboxableToPrimitive(Integer.TYPE, new Object(), false));
+  }
+
+  public void testIsUnboxableToPrimitiveAllWideningPrimitives() {
+    Object[] testValues =
+        new Object[] {new Byte((byte) 42), new Short((short) 42), new Integer(42), new Long(42L),
+            new Float(42.0f), new Double(42.0), new Character('a'), Boolean.TRUE};
+    boolean[] byteExpected = new boolean[] {true, false, false, false, false, false, false, false};
+    boolean[] shortExpected = new boolean[] {true, true, false, false, false, false, true, false};
+    boolean[] intExpected = new boolean[] {true, true, true, false, false, false, true, false};
+    boolean[] longExpected = new boolean[] {true, true, true, true, false, false, true, false};
+    boolean[] floatExpected = new boolean[] {true, true, true, false, true, false, true, false};
+    boolean[] doubleExpected = new boolean[] {true, true, true, true, true, true, true, false};
+    boolean[] charExpected = new boolean[] {true, true, true, false, false, false, true, false};
+    boolean[] booleanExpected =
+        new boolean[] {false, false, false, false, false, false, false, true};
+
+    for (int i = 0; i < testValues.length; ++i) {
+      assertEquals("Convert byte from " + testValues[i].getClass(), byteExpected[i], AndroidMock
+          .isUnboxableToPrimitive(Byte.TYPE, testValues[i], false));
+      assertEquals("Convert short from " + testValues[i].getClass(), shortExpected[i], AndroidMock
+          .isUnboxableToPrimitive(Short.TYPE, testValues[i], false));
+      assertEquals("Convert int from " + testValues[i].getClass(), intExpected[i], AndroidMock
+          .isUnboxableToPrimitive(Integer.TYPE, testValues[i], false));
+      assertEquals("Convert long from " + testValues[i].getClass(), longExpected[i], AndroidMock
+          .isUnboxableToPrimitive(Long.TYPE, testValues[i], false));
+      assertEquals("Convert float from " + testValues[i].getClass(), floatExpected[i], AndroidMock
+          .isUnboxableToPrimitive(Float.TYPE, testValues[i], false));
+      assertEquals("Convert double from " + testValues[i].getClass(), doubleExpected[i],
+          AndroidMock.isUnboxableToPrimitive(Double.TYPE, testValues[i], false));
+      assertEquals("Convert char from " + testValues[i].getClass(), charExpected[i], AndroidMock
+          .isUnboxableToPrimitive(Character.TYPE, testValues[i], false));
+      assertEquals("Convert boolean from " + testValues[i].getClass(), booleanExpected[i],
+          AndroidMock.isUnboxableToPrimitive(Boolean.TYPE, testValues[i], false));
+    }
+  }
+
+
+  public void testIsUnboxableToPrimitiveNotPrimitive() {
+    try {
+      AndroidMock.isUnboxableToPrimitive(Object.class, Object.class, false);
+      fail("Exception should have been thrown");
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+  }
+
+  public void testCreateMock() throws ClassNotFoundException, IOException, CannotCompileException,
+      NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<String> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.expect(mockVector.get(0)).andReturn("Hello World");
+    AndroidMock.replay(mockVector);
+    assertEquals("Hello World", mockVector.get(0).toString());
+    AndroidMock.verify(mockVector);
+  }
+
+  public void testCreateMockUsingParameters() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+    compileClasses(mockClasses);
+    SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 0, "GMT");
+    AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42);
+    AndroidMock.replay(mockTimeZone);
+    assertEquals(42, mockTimeZone.getRawOffset());
+    AndroidMock.verify(mockTimeZone);
+  }
+
+  public void testCreateMockUsingProtectedConstructors() throws ClassNotFoundException,
+      IOException, CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Calendar.class);
+    compileClasses(mockClasses);
+    Calendar mockCalendar = AndroidMock.createMock(Calendar.class);
+    AndroidMock.expect(mockCalendar.getGreatestMinimum(1)).andReturn(42);
+    AndroidMock.replay(mockCalendar);
+    assertEquals(42, mockCalendar.getGreatestMinimum(1));
+    AndroidMock.verify(mockCalendar);
+
+    // Just don't explode
+    Calendar newMockCalendar =
+        AndroidMock.createMock(Calendar.class, new SimpleTimeZone(1, "GMT"), Locale.UK);
+  }
+
+  public void testCreateMockUsingCastableParameters() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+    compileClasses(mockClasses);
+    SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 'a', "GMT");
+    AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42);
+    AndroidMock.replay(mockTimeZone);
+    assertEquals(42, mockTimeZone.getRawOffset());
+    AndroidMock.verify(mockTimeZone);
+  }
+
+  public void testCreateMockUsingUnusableParameters() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+    compileClasses(mockClasses);
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, "GMT");
+      fail("Excepted an IllegalArgumentException for incorrect number of constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 0, null);
+      fail("Excepted an IllegalArgumentException for indeterminate null constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createMock(SimpleTimeZone.class, 0, new Object());
+      fail("Excepted an IllegalArgumentException for incorrect constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+  }
+
+  public void testCreateMockUsingInterface() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Map.class);
+    compileClasses(mockClasses);
+    Map<String, String> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get("key")).andReturn("Hello World");
+    AndroidMock.replay(mockMap);
+    assertEquals("Hello World", mockMap.get("key"));
+    AndroidMock.verify(mockMap);
+  }
+
+  public void testCreateMockUsingClass() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<String> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.expect(mockVector.get(0)).andReturn("Hello World");
+    AndroidMock.replay(mockVector);
+    assertEquals("Hello World", mockVector.get(0).toString());
+    AndroidMock.verify(mockVector);
+  }
+
+  public void testCreateNiceMock() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<String> mockVector = AndroidMock.createNiceMock(Vector.class);
+    AndroidMock.expect(mockVector.get(0)).andReturn("Hello World");
+    AndroidMock.replay(mockVector);
+    assertEquals("Hello World", mockVector.get(0).toString());
+    AndroidMock.verify(mockVector);
+  }
+
+  public void testCreateNiceMockUsingUnusableParameters() throws ClassNotFoundException,
+      IOException, CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+    compileClasses(mockClasses);
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, "GMT");
+      fail("Excepted an IllegalArgumentException for incorrect number of constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, 0, null);
+      fail("Excepted an IllegalArgumentException for indeterminate null constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+    try {
+      SimpleTimeZone mockTimeZone =
+          AndroidMock.createNiceMock(SimpleTimeZone.class, 0, new Object());
+      fail("Excepted an IllegalArgumentException for incorrect constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+  }
+
+  public void testCreateNiceMockUsingParameters() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+
+    compileClasses(mockClasses);
+    SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, 0, "GMT");
+    AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42);
+    AndroidMock.replay(mockTimeZone);
+    assertEquals(42, mockTimeZone.getRawOffset());
+    AndroidMock.verify(mockTimeZone);
+  }
+
+  public void testCreateNiceMockUsingCastableParameters() throws ClassNotFoundException,
+      IOException, CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+
+    compileClasses(mockClasses);
+    SimpleTimeZone mockTimeZone = AndroidMock.createNiceMock(SimpleTimeZone.class, 'a', "GMT");
+    AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42);
+    AndroidMock.replay(mockTimeZone);
+    assertEquals(42, mockTimeZone.getRawOffset());
+    AndroidMock.verify(mockTimeZone);
+  }
+
+  public void testCreateNiceMockUsingInterface() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Map.class);
+
+    compileClasses(mockClasses);
+    Map<String, String> mockMap = AndroidMock.createNiceMock(Map.class);
+    AndroidMock.expect(mockMap.get("key")).andReturn("Hello World");
+    AndroidMock.replay(mockMap);
+    assertEquals("Hello World", mockMap.get("key"));
+    AndroidMock.verify(mockMap);
+  }
+
+  public void testCreateNiceMockUsingClass() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+
+    compileClasses(mockClasses);
+    Vector<String> mockVector = AndroidMock.createNiceMock(Vector.class);
+    AndroidMock.expect(mockVector.get(0)).andReturn("Hello World");
+    AndroidMock.replay(mockVector);
+    assertEquals("Hello World", mockVector.get(0).toString());
+    AndroidMock.verify(mockVector);
+  }
+
+  public void testCreateStrictMock() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+
+    compileClasses(mockClasses);
+    Vector<String> mockVector = AndroidMock.createStrictMock(Vector.class);
+    AndroidMock.expect(mockVector.get(0)).andReturn("Hello World");
+    AndroidMock.replay(mockVector);
+    assertEquals("Hello World", mockVector.get(0).toString());
+    AndroidMock.verify(mockVector);
+  }
+
+  public void testCreateStrictMockUsingUnusableParameters() throws ClassNotFoundException,
+      IOException, CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+
+    compileClasses(mockClasses);
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, "GMT");
+      fail("Excepted an IllegalArgumentException for incorrect number of constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+    try {
+      SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, 0, null);
+      fail("Excepted an IllegalArgumentException for indeterminate null constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+    try {
+      SimpleTimeZone mockTimeZone =
+          AndroidMock.createStrictMock(SimpleTimeZone.class, 0, new Object());
+      fail("Excepted an IllegalArgumentException for incorrect constructor parameters");
+    } catch (IllegalArgumentException e) {
+      // Expected
+    }
+  }
+
+  public void testCreateStrictMockUsingParameters() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+
+    compileClasses(mockClasses);
+    SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, 0, "GMT");
+    AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42);
+    AndroidMock.replay(mockTimeZone);
+    assertEquals(42, mockTimeZone.getRawOffset());
+    AndroidMock.verify(mockTimeZone);
+  }
+
+  public void testCreateStrictMockUsingCastableParameters() throws ClassNotFoundException,
+      IOException, CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(SimpleTimeZone.class);
+
+    compileClasses(mockClasses);
+    SimpleTimeZone mockTimeZone = AndroidMock.createStrictMock(SimpleTimeZone.class, 'a', "GMT");
+    AndroidMock.expect(mockTimeZone.getRawOffset()).andReturn(42);
+    AndroidMock.replay(mockTimeZone);
+    assertEquals(42, mockTimeZone.getRawOffset());
+    AndroidMock.verify(mockTimeZone);
+  }
+
+  public void testCreateStrictMockUsingInterface() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Map.class);
+
+    compileClasses(mockClasses);
+    Map<String, String> mockMap = AndroidMock.createStrictMock(Map.class);
+    AndroidMock.expect(mockMap.get("key")).andReturn("Hello World");
+    AndroidMock.replay(mockMap);
+    assertEquals("Hello World", mockMap.get("key"));
+    AndroidMock.verify(mockMap);
+  }
+
+  public void testCreateStrictMockUsingClass() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<String> mockVector = AndroidMock.createStrictMock(Vector.class);
+    AndroidMock.expect(mockVector.get(0)).andReturn("Hello World");
+    AndroidMock.replay(mockVector);
+    assertEquals("Hello World", mockVector.get(0).toString());
+    AndroidMock.verify(mockVector);
+  }
+
+  public void testCreateMockConstructorDoesWorkOnAllReturnTypes() throws ClassNotFoundException,
+      IOException, CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(ClassDoesWorkInConstructor.class);
+    compileClasses(mockClasses);
+    ClassDoesWorkInConstructor mock = AndroidMock.createMock(ClassDoesWorkInConstructor.class);
+  }
+
+  public void testAllForwardedMethods() throws CannotCompileException, NotFoundException {
+    for (CtMethod method : getForwardedMethods()) {
+      MethodVerifier verifier = new MethodVerifier(method);
+      // CtMethod.instrument Causes every instruction in the method to be
+      // inspected, and passed to
+      // the MethodVerifier callback (extends javassist.expr.ExprEditor). We
+      // want to verify that
+      // the expected EasyMock method is called at least once in each
+      // AndroidMock method.
+      method.instrument(verifier);
+      assertTrue(method.getLongName() + " not called.", verifier.expectedMethodCalled());
+    }
+  }
+
+  public void testCheckOrder() throws ClassNotFoundException, IOException, CannotCompileException,
+      NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.checkOrder(mockVector, false);
+    AndroidMock.checkOrder(AndroidMock.createMock(Map.class), false);
+  }
+
+  public void testVerify() throws ClassNotFoundException, IOException, CannotCompileException,
+      NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.replay(mockVector);
+    AndroidMock.verify(mockVector);
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.replay(mockMap);
+    AndroidMock.verify(mockMap);
+  }
+
+  public void testResetToStrict() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.resetToStrict(mockVector);
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.resetToStrict(mockMap);
+  }
+
+  public void testResetToDefault() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.resetToDefault(mockVector);
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.resetToDefault(mockMap);
+  }
+
+  public void testResetToNice() throws ClassNotFoundException, IOException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.resetToNice(mockVector);
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.resetToNice(mockMap);
+  }
+
+  public void testReset() throws ClassNotFoundException, IOException, CannotCompileException,
+      NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.reset(mockVector);
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.reset(mockMap);
+
+  }
+
+  public void testReplay() throws ClassNotFoundException, IOException, CannotCompileException,
+      NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(Vector.class);
+    compileClasses(mockClasses);
+    Vector<?> mockVector = AndroidMock.createMock(Vector.class);
+    AndroidMock.replay(mockVector);
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testExpect() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    mockMap.clear();
+    AndroidMock.expect(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testExpectLastCall() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    mockMap.clear();
+    AndroidMock.expectLastCall();
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyBoolean() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyBoolean())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyByte() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyByte())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyChar() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyChar())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyInt() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyInt())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyLong() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyLong())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyFloat() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyFloat())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyDouble() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyDouble())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyShort() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyShort())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnyObject() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.anyObject())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testGeq() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq((byte) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq((short) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq(0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq(0L))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq(0.0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq(0.0f))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.geq("Hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testLeq() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq((byte) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq((short) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq(0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq(0L))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq(0.0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq(0.0f))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.leq("Hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testGt() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt((byte) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt((short) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt(0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt(0L))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt(0.0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt(0.0f))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.gt("Hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testLt() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt((byte) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt((short) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt(0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt(0L))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt(0.0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt(0.0f))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.lt("Hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testIsA() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.isA(String.class))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testContains() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.contains("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAnd() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(true), AndroidMock.eq(true))))
+        .andReturn(null);
+    AndroidMock.expect(
+        mockMap.get(AndroidMock.and(AndroidMock.eq((byte) 0), AndroidMock.eq((byte) 0))))
+        .andReturn(null);
+    AndroidMock.expect(
+        mockMap.get(AndroidMock.and(AndroidMock.eq((short) 0), AndroidMock.eq((short) 0))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0), AndroidMock.eq(0))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0L), AndroidMock.eq(0L))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0.0), AndroidMock.eq(0.0))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq(0.0f), AndroidMock.eq(0.0f))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq("hi"), AndroidMock.eq("hi"))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.and(AndroidMock.eq('a'), AndroidMock.eq('a'))))
+        .andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testOr() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(true), AndroidMock.eq(true))))
+        .andReturn(null);
+    AndroidMock.expect(
+        mockMap.get(AndroidMock.or(AndroidMock.eq((byte) 0), AndroidMock.eq((byte) 0))))
+        .andReturn(null);
+    AndroidMock.expect(
+        mockMap.get(AndroidMock.or(AndroidMock.eq((short) 0), AndroidMock.eq((short) 0))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0), AndroidMock.eq(0))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0L), AndroidMock.eq(0L))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0.0), AndroidMock.eq(0.0))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq(0.0f), AndroidMock.eq(0.0f))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq("hi"), AndroidMock.eq("hi"))))
+        .andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.or(AndroidMock.eq('a'), AndroidMock.eq('a'))))
+        .andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testNot() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(true)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq((byte) 0)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq((short) 0)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0L)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0.0)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq(0.0f)))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq("hi")))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.not(AndroidMock.eq('a')))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testEq() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(true))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq((byte) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq((short) 0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(0L))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0f))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0, 0.1))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq(0.0f, 0.1f))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq("hi"))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.eq('a'))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAryEq() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new boolean[] {true}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new byte[] {(byte) 0}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new short[] {(short) 0}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new int[] {0}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new long[] {0L}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new double[] {0.0}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new float[] {0.0f}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new String[] {"hi"}))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.aryEq(new char[] {'a'}))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testIsNull() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.isNull())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testNotNull() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.notNull())).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testFind() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.find("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testMatches() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.matches("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testStartsWith() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.startsWith("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testEndsWith() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.endsWith("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testSame() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.same("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testCmpEq() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.cmpEq("hi"))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testCmp() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(
+        mockMap.get(AndroidMock.cmp("hi", String.CASE_INSENSITIVE_ORDER, LogicalOperator.EQUAL)))
+        .andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testCapture() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<Byte>()))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<Character>()))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<Double>()))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<Float>()))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<Integer>()))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<Long>()))).andReturn(null);
+    AndroidMock.expect(mockMap.get(AndroidMock.capture(new Capture<String>()))).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testReportMatcher() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.reportMatcher(new Equals(null));
+    AndroidMock.expect(mockMap.get(null)).andReturn(null);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testGetCurrentArguments() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.expect(mockMap.get(null)).andAnswer(new IAnswer() {
+      @Override
+      public Object answer() {
+        AndroidMock.getCurrentArguments();
+        return null;
+      }
+    });
+    AndroidMock.replay(mockMap);
+    mockMap.get(null);
+  }
+
+  public void testMakeThreadSafe() {
+    Map<?, ?> mockMap = AndroidMock.createMock(Map.class);
+    AndroidMock.makeThreadSafe(mockMap, false);
+    AndroidMock.replay(mockMap);
+  }
+
+  public void testAndThrowsOnMockedInterface() throws IOException {
+    ObjectInput mockInStream = AndroidMock.createMock(ObjectInput.class);
+    AndroidMock.expect(mockInStream.read()).andThrow(new IOException("foo"));
+    AndroidMock.replay(mockInStream);
+    try {
+      mockInStream.read();
+      fail("IOException not thrown");
+    } catch (IOException e) {
+      assertEquals("foo", e.getMessage());
+    }
+    AndroidMock.verify(mockInStream);
+  }
+
+  public void testAndThrowsOnMockedClass() throws IOException, ClassNotFoundException,
+      CannotCompileException, NotFoundException {
+    List<GeneratedClassFile> mockClasses =
+        new AndroidMockGenerator().createMocksForClass(InputStream.class);
+    compileClasses(mockClasses);
+    InputStream mockInStream = AndroidMock.createMock(InputStream.class);
+    AndroidMock.expect(mockInStream.read()).andThrow(new IOException("foo"));
+    AndroidMock.replay(mockInStream);
+    try {
+      mockInStream.read();
+      fail("IOException not thrown");
+    } catch (IOException e) {
+      assertEquals("foo", e.getMessage());
+    }
+    AndroidMock.verify(mockInStream);
+  }
+
+  /**
+   * Used for testing that a given method on Android Mock calls the equivalent
+   * method on EasyMock, to ensure that the method-wiring of Android Mock is
+   * correct.
+   * 
+   * @author swoodward@google.com (Stephen Woodward)
+   */
+  class MethodVerifier extends ExprEditor {
+    private CtMethod expectedMethod;
+    private boolean methodCalled;
+
+    MethodVerifier(CtMethod expectedMethod) {
+      this.expectedMethod = expectedMethod;
+    }
+
+    @Override
+    public void edit(MethodCall calledMethod) {
+      try {
+        methodCalled = methodCalled || expectedMethod.equals(calledMethod.getMethod());
+      } catch (NotFoundException e) {
+        throw new RuntimeException(e);
+      }
+    }
+
+    public boolean expectedMethodCalled() {
+      return methodCalled;
+    }
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java b/tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java
new file mode 100644
index 0000000..a8c6a55
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassDoesWorkInConstructor.java
@@ -0,0 +1,77 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+
+/**
+ * Support class for testing.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassDoesWorkInConstructor {
+  public ClassDoesWorkInConstructor() {
+    this.fooInt(1);
+    this.fooByte((byte) 1);
+    this.fooShort((short) 1);
+    this.fooChar('a');
+    this.fooLong(1L);
+    this.fooFloat(1.0f);
+    this.fooDouble(1.0);
+    this.fooBoolean(true);
+    this.fooObject("hello");
+    this.fooVoid();
+  }
+
+  public void fooVoid() {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public Object fooObject(String string) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public boolean fooBoolean(boolean b) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public double fooDouble(double d) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public float fooFloat(float f) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public long fooLong(long i) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public char fooChar(char c) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public short fooShort(short s) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public byte fooByte(byte b) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+
+  public int fooInt(int i) {
+    throw new IllegalStateException("I wasn't mocked!!");
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java b/tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java
new file mode 100644
index 0000000..6745b91
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassHasDelegateMethods.java
@@ -0,0 +1,38 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Class with methods that match the delegate methods. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassHasDelegateMethods {
+  /**
+   * Test method.
+   * @param obj test obj.
+   */
+  public void setDelegate___AndroidMock(Object obj) {
+  }
+
+  /**
+   * Test method
+   * @return null
+   */
+  public Object getDelegate___AndroidMock() {
+    return null;
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassHasFinalMethods.java b/tests/com/google/android/testing/mocking/ClassHasFinalMethods.java
new file mode 100644
index 0000000..414f5f8
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassHasFinalMethods.java
@@ -0,0 +1,35 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Class with final methods. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassHasFinalMethods {
+  public final int foo() {
+    return 0;
+  }
+
+  public int bar() {
+    return 0;
+  }
+
+  public final int foobar() {
+    return 0;
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java b/tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java
new file mode 100644
index 0000000..8b97cd8
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassHasNoDefaultConstructor.java
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Class with no default constructor. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassHasNoDefaultConstructor {
+  public ClassHasNoDefaultConstructor(int foo) {
+
+  }
+
+  public int foo() {
+    return 0;
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java b/tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java
new file mode 100644
index 0000000..20533ee
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassHasNoPublicConstructors.java
@@ -0,0 +1,27 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Class with no public constructor. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassHasNoPublicConstructors {
+  private ClassHasNoPublicConstructors() {
+
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java b/tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java
new file mode 100644
index 0000000..f1b04fa
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassHasOverloadedMethods.java
@@ -0,0 +1,30 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Class with overloaded methods. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassHasOverloadedMethods {
+  public int foo() {
+    return 0;
+  }
+
+  public void foo(int arg) {
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassHasStaticMethods.java b/tests/com/google/android/testing/mocking/ClassHasStaticMethods.java
new file mode 100644
index 0000000..29f4f52
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassHasStaticMethods.java
@@ -0,0 +1,31 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Class with static methods. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassHasStaticMethods {
+  public static int staticFoo() {
+    return 0;
+  }
+
+  public int foo() {
+    return 1;
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassIsAnnotation.java b/tests/com/google/android/testing/mocking/ClassIsAnnotation.java
new file mode 100644
index 0000000..e42c8e1
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassIsAnnotation.java
@@ -0,0 +1,25 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Annotation Class. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public @interface ClassIsAnnotation {
+
+}
diff --git a/tests/com/google/android/testing/mocking/ClassIsEnum.java b/tests/com/google/android/testing/mocking/ClassIsEnum.java
new file mode 100644
index 0000000..b7fa957
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassIsEnum.java
@@ -0,0 +1,25 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Enum Class. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public enum ClassIsEnum {
+  One, Two, Three, Four;
+}
diff --git a/tests/com/google/android/testing/mocking/ClassIsFinal.java b/tests/com/google/android/testing/mocking/ClassIsFinal.java
new file mode 100644
index 0000000..88f8279
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassIsFinal.java
@@ -0,0 +1,27 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Final Class. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public final class ClassIsFinal {
+  public int foo() {
+    return 0;
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ClassIsInterface.java b/tests/com/google/android/testing/mocking/ClassIsInterface.java
new file mode 100644
index 0000000..d48f512
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassIsInterface.java
@@ -0,0 +1,25 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+/**
+ * Interface. Used only for testing.
+ *
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public interface ClassIsInterface {
+  int foo();
+}
diff --git a/tests/com/google/android/testing/mocking/ClassTypeTests.java b/tests/com/google/android/testing/mocking/ClassTypeTests.java
new file mode 100644
index 0000000..a4d60c2
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ClassTypeTests.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+import javassist.ClassPool;
+import javassist.CtClass;
+import javassist.CtMethod;
+import javassist.NotFoundException;
+
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * Various tests that verify that different types of Classes are handled
+ * correctly.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ClassTypeTests extends TestCase {
+  private AndroidMockGenerator androidMockGenerator = new AndroidMockGenerator();
+
+  private AndroidMockGenerator getAndroidMockGenerator() {
+    return androidMockGenerator;
+  }
+
+  private void assertAllMethodNames(List<String> expectedNames,
+      Map<String, List<String>> expectedMethods, List<GeneratedClassFile> classes)
+      throws IOException {
+    for (GeneratedClassFile clazz : classes) {
+      assertTrue(expectedNames.contains(clazz.getClassName()));
+      assertUnorderedContentsSame(expectedMethods.get(clazz.getClassName()), getMethodNames(clazz));
+    }
+  }
+
+  private <T> void assertUnorderedContentsSame(Iterable<T> expected, Iterable<T> actual) {
+    List<T> missingItems = new ArrayList<T>();
+    List<T> extraItems = new ArrayList<T>();
+    for (T item : expected) {
+      missingItems.add(item);
+    }
+    for (T item : actual) {
+      missingItems.remove(item);
+      extraItems.add(item);
+    }
+    for (T item : expected) {
+      extraItems.remove(item);
+    }
+    if (missingItems.size() + extraItems.size() != 0) {
+      String errorMessage =
+          "Contents were different. Missing: " + Arrays.toString(missingItems.toArray())
+              + " Extra: " + Arrays.toString(extraItems.toArray());
+      fail(errorMessage);
+    }
+  }
+
+  private List<String> getExpectedNames(Class<?> clazz) {
+    return new ArrayList<String>(Arrays.asList(new String[] {
+        "genmocks." + clazz.getCanonicalName() + "DelegateInterface",
+        "genmocks." + clazz.getCanonicalName() + "DelegateSubclass"}));
+  }
+
+  private Iterable<String> getMethodNames(GeneratedClassFile clazz) throws IOException {
+    ByteArrayInputStream classInputStream = new ByteArrayInputStream(clazz.getContents());
+    CtClass ctClass;
+    try {
+      ctClass = ClassPool.getDefault().getCtClass(clazz.getClassName());
+      if (ctClass.isFrozen()) {
+        ctClass.defrost();
+      }
+    } catch (NotFoundException e) {
+      // That's ok, we're just defrosting any classes that affect us that were created
+      // by other tests.  NotFoundException implies the class is not frozen.
+    }
+    ctClass = ClassPool.getDefault().makeClass(classInputStream);
+    return getMethodNames(ctClass.getDeclaredMethods());
+  }
+
+  private List<String> getMethodNames(CtMethod[] methods) {
+    List<String> methodNames = new ArrayList<String>();
+    for (CtMethod method : methods) {
+      methodNames.add(method.getName());
+    }
+    return methodNames;
+  }
+
+  private List<String> getMethodNames(Method[] methods, String[] exclusions) {
+    List<String> methodNames = new ArrayList<String>();
+    for (Method method : methods) {
+      if (!Arrays.asList(exclusions).contains(method.getName())) {
+        methodNames.add(method.getName());
+      }
+    }
+    return methodNames;
+  }
+
+  private Map<String, List<String>> getExpectedMethodsMap(List<String> expectedNames,
+      Class<?> clazz) {
+    return getExpectedMethodsMap(expectedNames, clazz, new String[0]);
+  }
+
+  private Map<String, List<String>> getExpectedMethodsMap(List<String> expectedNames,
+      Class<?> clazz, String[] exclusions) {
+    Map<String, List<String>> expectedMethods = new HashMap<String, List<String>>();
+    expectedMethods.put(expectedNames.get(0), new ArrayList<String>(Arrays.asList(new String[] {
+        "finalize", "clone"})));
+    expectedMethods.put(expectedNames.get(1), new ArrayList<String>(Arrays.asList(new String[] {
+        "finalize", "clone", "setDelegate___AndroidMock", "getDelegate___AndroidMock"})));
+    expectedMethods.get(expectedNames.get(0)).addAll(
+        getMethodNames(clazz.getDeclaredMethods(), exclusions));
+    expectedMethods.get(expectedNames.get(1)).addAll(
+        getMethodNames(clazz.getDeclaredMethods(), exclusions));
+    return expectedMethods;
+  }
+
+  public void testClassIsDuplicate() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    List<GeneratedClassFile> classList =
+        getAndroidMockGenerator().createMocksForClass(Object.class);
+    List<GeneratedClassFile> secondClassList =
+        getAndroidMockGenerator().createMocksForClass(Object.class);
+    assertEquals(classList, secondClassList);
+  }
+
+  public void testClassHasDelegateMethods() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    List<String> expectedNames = getExpectedNames(ClassHasDelegateMethods.class);
+    Map<String, List<String>> expectedMethods =
+        getExpectedMethodsMap(expectedNames, ClassHasDelegateMethods.class,
+            new String[] {"getDelegate___AndroidMock"});
+    // This use case doesn't fit our util in any nice way, so just tweak it.
+    expectedMethods.get(
+        "genmocks.com.google.android.testing.mocking.ClassHasDelegateMethodsDelegateInterface")
+        .add("getDelegate___AndroidMock");
+
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes =
+        mockGenerator.createMocksForClass(ClassHasDelegateMethods.class);
+    assertEquals(2, classes.size());
+    assertAllMethodNames(expectedNames, expectedMethods, classes);
+  }
+
+  public void testClassHasFinalMethods() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    List<String> expectedNames = getExpectedNames(ClassHasFinalMethods.class);
+    Map<String, List<String>> expectedMethods =
+        getExpectedMethodsMap(expectedNames, ClassHasFinalMethods.class, new String[] {"foo",
+            "foobar"});
+
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes =
+        mockGenerator.createMocksForClass(ClassHasFinalMethods.class);
+    assertEquals(2, classes.size());
+    assertAllMethodNames(expectedNames, expectedMethods, classes);
+  }
+
+  public void testClassHasNoDefaultConstructor() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes =
+        mockGenerator.createMocksForClass(ClassHasNoDefaultConstructor.class);
+    assertEquals(2, classes.size());
+  }
+
+  public void testClassHasNoPublicConstructors() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes =
+        mockGenerator.createMocksForClass(ClassHasNoPublicConstructors.class);
+    assertEquals(0, classes.size());
+  }
+
+  public void testClassHasOverloadedMethods() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    List<String> expectedNames = getExpectedNames(ClassHasOverloadedMethods.class);
+    Map<String, List<String>> expectedMethods =
+        getExpectedMethodsMap(expectedNames, ClassHasOverloadedMethods.class);
+
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes =
+        mockGenerator.createMocksForClass(ClassHasOverloadedMethods.class);
+    assertEquals(2, classes.size());
+    assertAllMethodNames(expectedNames, expectedMethods, classes);
+  }
+
+  public void testClassHasStaticMethods() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    List<String> expectedNames = getExpectedNames(ClassHasStaticMethods.class);
+    Map<String, List<String>> expectedMethods =
+        getExpectedMethodsMap(expectedNames, ClassHasStaticMethods.class,
+            new String[] {"staticFoo"});
+
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes =
+        mockGenerator.createMocksForClass(ClassHasStaticMethods.class);
+    assertEquals(2, classes.size());
+    assertAllMethodNames(expectedNames, expectedMethods, classes);
+  }
+
+  public void testClassIsAnnotation() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(ClassIsAnnotation.class);
+    assertEquals(0, classes.size());
+  }
+
+  public void testClassIsEnum() throws ClassNotFoundException, IOException, CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(ClassIsEnum.class);
+    assertEquals(0, classes.size());
+  }
+
+  public void testClassIsFinal() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(ClassIsFinal.class);
+    assertEquals(0, classes.size());
+  }
+
+  public void testClassIsInterface() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(ClassIsInterface.class);
+    assertEquals(0, classes.size());
+  }
+
+  public void testClassIsArray() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Object[].class);
+    assertEquals(0, classes.size());
+  }
+
+  public void testClassIsNormal() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Object.class);
+    assertEquals(2, classes.size());
+  }
+
+  public void testClassIsPrimitive() throws ClassNotFoundException, IOException,
+      CannotCompileException {
+    AndroidMockGenerator mockGenerator = getAndroidMockGenerator();
+    List<GeneratedClassFile> classes = mockGenerator.createMocksForClass(Integer.TYPE);
+    assertEquals(0, classes.size());
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/ConstructorCreationTests.java b/tests/com/google/android/testing/mocking/ConstructorCreationTests.java
new file mode 100644
index 0000000..152918d
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/ConstructorCreationTests.java
@@ -0,0 +1,131 @@
+/*
+ *  Copyright 2010 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.google.android.testing.mocking;
+
+import junit.framework.TestCase;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+
+
+/**
+ * Tests for mocked objects with non default constructors.
+ * 
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class ConstructorCreationTests extends TestCase {
+  public static class Foo {
+    private int value;
+    Foo(int value) { this.value = value; }
+    int get() { return value; }
+  }
+
+  public static class Bar {
+    private double value;
+    Bar(double value) { this.value = value; }
+    double get() { return value; }
+  }
+
+  public static class TestClass {
+    public int v1;
+    public double v2;
+    public boolean usedFloatConstructor;
+    
+    public TestClass(Foo foo) {
+      this(foo.get());
+    }
+
+    public TestClass(Foo foo, Bar bar) {
+      this(foo.get(), bar.get());
+    }
+
+    public TestClass(int v1) {
+      this(v1, 0);
+    }
+
+    public TestClass(int v1, float v2) {
+      this.v1 = v1;
+      this.v2 = v2;
+      usedFloatConstructor = true;
+    }
+
+    public TestClass(int v1, double v2) {
+      this.v1 = v1;
+      this.v2 = (int) v2;
+      usedFloatConstructor = false;
+    }
+  }
+
+  private void hasConstructor(Object... args) {
+    Constructor<TestClass> constructor =
+        AndroidMock.getConstructorFor(TestClass.class, args);
+    assertNotNull(constructor);
+  }
+
+  private void doesNotHaveConstructor(Object... args) {
+    try {
+      Constructor<TestClass> constructor =
+          AndroidMock.getConstructorFor(TestClass.class, args);
+      fail("A constructor was found: " + constructor);
+    } catch (IllegalArgumentException e) {
+      // expected
+    }
+  }
+
+  public void testConstructors() {
+    hasConstructor(new Foo(1));
+    doesNotHaveConstructor(new Bar(2));
+    hasConstructor(new Foo(1), new Bar(2));
+    hasConstructor(1);
+    hasConstructor(1, 2);
+    doesNotHaveConstructor(new Foo(1), 2);
+    hasConstructor(1, new Integer("2"));
+    hasConstructor(1, 2.0);
+    hasConstructor(1, 2.0f);
+  }
+
+  private void checkConstructor(Object[] args, Type[] expectedTypes) {
+    Constructor<TestClass> constructor =
+        AndroidMock.getConstructorFor(TestClass.class, args);
+    assertNotNull(constructor);
+    Type[] types = constructor.getGenericParameterTypes();
+    assertEquals(expectedTypes.length, types.length);
+    for (int i = 0; i < expectedTypes.length; ++i) {
+      assertEquals(expectedTypes[i], types[i]);
+    }
+  }
+
+  public void testCorrectConstructor() {
+    checkConstructor(
+            new Object[]{new Foo(1)},
+            new Type[]{Foo.class});
+    checkConstructor(
+            new Object[]{new Foo(1), new Bar(2)},
+            new Type[]{Foo.class, Bar.class});
+    checkConstructor(
+            new Object[]{1},
+            new Type[]{Integer.TYPE});
+    checkConstructor(
+            new Object[]{1, new Float("2")},
+            new Type[]{Integer.TYPE, Float.TYPE});
+    checkConstructor(
+            new Object[]{1, 2.0},
+            new Type[]{Integer.TYPE, Double.TYPE});
+    checkConstructor(
+            new Object[]{1, 2.0f},
+            new Type[]{Integer.TYPE, Float.TYPE});
+  }
+}
\ No newline at end of file
diff --git a/tests/com/google/android/testing/mocking/FileUtilsTest.java b/tests/com/google/android/testing/mocking/FileUtilsTest.java
new file mode 100644
index 0000000..b1058e3
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/FileUtilsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import junit.framework.TestCase;
+
+import java.util.Vector;
+
+/**
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class FileUtilsTest extends TestCase {
+  public void testGetFilenameForClass() {
+    assertEquals("java/lang/Object.class", FileUtils.getFilenameFor(Object.class.getName()));
+    assertEquals("com/google/android/testing/mocking/FileUtilsTest$InnerClass.class",
+        FileUtils.getFilenameFor(InnerClass.class.getName()));
+  }
+
+  public void testGetClassNameFor() {
+    assertEquals("java/lang/Object.class", FileUtils.getFilenameFor(Object.class.getName()));
+    assertEquals("com/google/android/testing/mocking/FileUtilsTest$InnerClass.class",
+        FileUtils.getFilenameFor(InnerClass.class.getName()));
+  }
+
+  public void testGetInterfaceNameFor() {
+    assertEquals("v15.genmocks.java.util.VectorDelegateInterface",
+        FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.CUPCAKE));
+    assertEquals("v16.genmocks.java.util.VectorDelegateInterface",
+        FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.DONUT));
+    assertEquals("v201.genmocks.java.util.VectorDelegateInterface",
+        FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.ECLAIR_0_1));
+    assertEquals("v21.genmocks.java.util.VectorDelegateInterface",
+        FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.ECLAIR_MR1));
+    assertEquals("v22.genmocks.java.util.VectorDelegateInterface",
+        FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.FROYO));
+    assertEquals("genmocks.java.util.VectorDelegateInterface",
+        FileUtils.getInterfaceNameFor(Vector.class, SdkVersion.UNKNOWN));
+  }
+
+  public void testGetSubclassNameFor() {
+    assertEquals("v15.genmocks.java.util.VectorDelegateSubclass",
+        FileUtils.getSubclassNameFor(Vector.class, SdkVersion.CUPCAKE));
+    assertEquals("v16.genmocks.java.util.VectorDelegateSubclass",
+        FileUtils.getSubclassNameFor(Vector.class, SdkVersion.DONUT));
+    assertEquals("v201.genmocks.java.util.VectorDelegateSubclass",
+        FileUtils.getSubclassNameFor(Vector.class, SdkVersion.ECLAIR_0_1));
+    assertEquals("v21.genmocks.java.util.VectorDelegateSubclass",
+        FileUtils.getSubclassNameFor(Vector.class, SdkVersion.ECLAIR_MR1));
+    assertEquals("v22.genmocks.java.util.VectorDelegateSubclass",
+        FileUtils.getSubclassNameFor(Vector.class, SdkVersion.FROYO));
+    assertEquals("genmocks.java.util.VectorDelegateSubclass",
+        FileUtils.getSubclassNameFor(Vector.class, SdkVersion.UNKNOWN));
+  }
+
+  class InnerClass {
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/SdkVersionTest.java b/tests/com/google/android/testing/mocking/SdkVersionTest.java
new file mode 100644
index 0000000..eb7c764
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/SdkVersionTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class SdkVersionTest extends TestCase {
+
+  public void testGetAllVersions() {
+    List<SdkVersion> versions = Arrays.asList(SdkVersion.getAllVersions());
+    List<SdkVersion> values = Arrays.asList(SdkVersion.values());
+    assertEquals(5, versions.size());
+    assertTrue(values.containsAll(versions));
+    assertFalse(versions.contains(SdkVersion.UNKNOWN));
+  }
+
+  public void testGetVersionName() {
+    assertEquals("v15", SdkVersion.CUPCAKE.getVersionName());
+    assertEquals("v16", SdkVersion.DONUT.getVersionName());
+    assertEquals("v201", SdkVersion.ECLAIR_0_1.getVersionName());
+    assertEquals("v21", SdkVersion.ECLAIR_MR1.getVersionName());
+    assertEquals("v22", SdkVersion.FROYO.getVersionName());
+    assertEquals("", SdkVersion.UNKNOWN.getVersionName());
+    assertEquals("Unknown new SDK has been added, update this test",
+        6, SdkVersion.values().length);
+  }
+
+  public void testGetPackagePrefix() {
+    assertEquals("v15.", SdkVersion.CUPCAKE.getPackagePrefix());
+    assertEquals("v16.", SdkVersion.DONUT.getPackagePrefix());
+    assertEquals("v201.", SdkVersion.ECLAIR_0_1.getPackagePrefix());
+    assertEquals("v21.", SdkVersion.ECLAIR_MR1.getPackagePrefix());
+    assertEquals("v22.", SdkVersion.FROYO.getPackagePrefix());
+    assertEquals("", SdkVersion.UNKNOWN.getPackagePrefix());
+    assertEquals("Unknown new SDK has been added, update this test",
+        6, SdkVersion.values().length);
+  }
+
+  public void testGetCurrentVersion() {
+    // Always UNKNOWN on the desktop
+    assertEquals(SdkVersion.UNKNOWN, SdkVersion.getCurrentVersion());
+  }
+
+  public void testGetVersionFor() {
+    assertEquals(SdkVersion.CUPCAKE, SdkVersion.getVersionFor(3));
+    assertEquals(SdkVersion.DONUT, SdkVersion.getVersionFor(4));
+    assertEquals(SdkVersion.ECLAIR_0_1, SdkVersion.getVersionFor(6));
+    assertEquals(SdkVersion.ECLAIR_MR1, SdkVersion.getVersionFor(7));
+    assertEquals(SdkVersion.FROYO, SdkVersion.getVersionFor(8));
+    assertEquals(SdkVersion.UNKNOWN, SdkVersion.getVersionFor(-1));
+    for (int i = 9; i < 50; ++i) {
+      assertEquals("Unknown new SDK has been added, update this test",
+          SdkVersion.UNKNOWN, SdkVersion.getVersionFor(i));
+    }
+  }
+}
diff --git a/tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java b/tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java
new file mode 100644
index 0000000..0b8961b
--- /dev/null
+++ b/tests/com/google/android/testing/mocking/UsesMocksProcessorTest.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright 2010 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.google.android.testing.mocking;
+
+import javassist.CannotCompileException;
+
+import junit.framework.TestCase;
+
+import org.easymock.EasyMock;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.type.TypeVisitor;
+import javax.tools.JavaFileObject;
+
+/**
+ * @author swoodward@google.com (Stephen Woodward)
+ */
+public class UsesMocksProcessorTest extends TestCase {
+
+  private Set<? extends Element> getAnnotatedElementsSet(Class<?>... classes) {
+    Set<Element> set = new HashSet<Element>();
+    for (Class<?> clazz : classes) {
+      set.add(getMockElement(clazz));
+    }
+    return set;
+  }
+
+  @SuppressWarnings("unchecked")
+  private Element getMockElement(Class<?> clazz) {
+    Element mockElement = EasyMock.createNiceMock(Element.class);
+    EasyMock.expect(mockElement.getAnnotationMirrors()).andReturn(getMockAnnotationMirrors(clazz))
+        .anyTimes();
+    EasyMock.replay(mockElement);
+    return mockElement;
+  }
+
+  @SuppressWarnings("unchecked")
+  private List getMockAnnotationMirrors(Class<?> clazz) {
+    List<AnnotationMirror> mockMirrorList = new ArrayList<AnnotationMirror>();
+    AnnotationMirror mockMirror = EasyMock.createNiceMock(AnnotationMirror.class);
+    EasyMock.expect(mockMirror.getAnnotationType()).andReturn(getMockAnnotationType()).anyTimes();
+    EasyMock.expect(mockMirror.getElementValues()).andReturn(getMockElementValuesMap(clazz))
+        .anyTimes();
+    EasyMock.replay(mockMirror);
+    mockMirrorList.add(mockMirror);
+    return mockMirrorList;
+  }
+
+  @SuppressWarnings("unchecked")
+  private Map getMockElementValuesMap(Class<?> clazz) {
+    Map mockValuesMap = new HashMap();
+    mockValuesMap.put(getMockExecutableElement(), getMockAnnotationValue(clazz));
+    return mockValuesMap;
+  }
+
+  private AnnotationValue getMockAnnotationValue(Class<?> clazz) {
+    AnnotationValue mockValue = EasyMock.createMock(AnnotationValue.class);
+    EasyMock.expect(mockValue.getValue()).andReturn(
+        Arrays.asList(new String[] {clazz.getName() + ".class"})).anyTimes();
+    EasyMock.replay(mockValue);
+    return mockValue;
+  }
+
+  private ExecutableElement getMockExecutableElement() {
+    ExecutableElement mockElement = EasyMock.createNiceMock(ExecutableElement.class);
+    EasyMock.replay(mockElement);
+    return mockElement;
+  }
+
+  private DeclaredType getMockAnnotationType() {
+    return new DeclaredType() {
+      @Override
+      public String toString() {
+        return UsesMocks.class.getName();
+      }
+
+      @Override
+      public Element asElement() {
+        return null;
+      }
+
+      @Override
+      public TypeMirror getEnclosingType() {
+        return null;
+      }
+
+      @Override
+      public List<? extends TypeMirror> getTypeArguments() {
+        return null;
+      }
+
+      @Override
+      public <R, P> R accept(TypeVisitor<R, P> v, P p) {
+        return null;
+      }
+
+      @Override
+      public TypeKind getKind() {
+        return null;
+      }
+    };
+  }
+
+  private UsesMocksProcessor getProcessor() {
+    return getProcessor(getMockProcessingEnvironment());
+  }
+
+  private UsesMocksProcessor getProcessor(ProcessingEnvironment processingEnv) {
+    UsesMocksProcessor processor = new UsesMocksProcessor();
+    processor.init(processingEnv);
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+    processor.logger = new ProcessorLogger(outputStream, processingEnv);
+    return processor;
+  }
+
+  private ProcessingEnvironment getMockProcessingEnvironment(Filer mockFiler) {
+    ProcessingEnvironment mockEnvironment = EasyMock.createNiceMock(ProcessingEnvironment.class);
+    EasyMock.expect(mockEnvironment.getMessager()).andReturn(getMockMessager()).anyTimes();
+    EasyMock.expect(mockEnvironment.getFiler()).andReturn(mockFiler).anyTimes();
+    EasyMock.expect(mockEnvironment.getOptions()).andReturn(getMockOptions()).anyTimes();
+    EasyMock.replay(mockEnvironment);
+    return mockEnvironment;
+  }
+
+  private Map<String, String> getMockOptions() {
+    Map<String, String> map = new HashMap<String, String>();
+    map.put("bin_dir", ".");
+    map.put("logfile", "logfile");
+    return map;
+  }
+
+  private ProcessingEnvironment getMockProcessingEnvironment() {
+    return getMockProcessingEnvironment(getMockFiler());
+  }
+
+  private Messager getMockMessager() {
+    Messager mockMessager = EasyMock.createNiceMock(Messager.class);
+    EasyMock.replay(mockMessager);
+    return mockMessager;
+  }
+
+  private Filer getMockFiler() {
+    try {
+      return getMockFiler(getMockFileObject());
+    } catch (IOException e) {
+      // Can't happen
+      throw new RuntimeException(e);
+    }
+  }
+
+  private Filer getMockFiler(JavaFileObject mockFileObject) {
+    Filer mockFiler = EasyMock.createNiceMock(Filer.class);
+    try {
+      EasyMock.expect(mockFiler.createClassFile((CharSequence) EasyMock.anyObject())).andReturn(
+          mockFileObject).anyTimes();
+    } catch (IOException e) {
+      // Can't happen
+      throw new RuntimeException(e);
+    }
+    EasyMock.replay(mockFiler);
+    return mockFiler;
+  }
+
+  private JavaFileObject getMockFileObject() throws IOException {
+    return getMockFileObject(new ByteArrayOutputStream());
+  }
+
+  private JavaFileObject getMockFileObject(OutputStream outStream) throws IOException {
+    JavaFileObject mockFileObject = EasyMock.createNiceMock(JavaFileObject.class);
+    EasyMock.expect(mockFileObject.openOutputStream()).andReturn(outStream).anyTimes();
+    EasyMock.replay(mockFileObject);
+    return mockFileObject;
+  }
+
+  private RoundEnvironment getMockRoundEnvironment(Set<? extends Element> elementsWithAnnotation) {
+    return getMockRoundEnvironment(elementsWithAnnotation, false);
+  }
+
+  @SuppressWarnings("unchecked")
+  private RoundEnvironment getMockRoundEnvironment(Set<? extends Element> elementsWithAnnotation,
+      boolean finishedProcessing) {
+    RoundEnvironment mockEnv = EasyMock.createNiceMock(RoundEnvironment.class);
+    EasyMock.expect(mockEnv.getElementsAnnotatedWith(UsesMocks.class)).andReturn(
+        (Set) elementsWithAnnotation).anyTimes();
+    EasyMock.expect(mockEnv.processingOver()).andReturn(finishedProcessing).anyTimes();
+    EasyMock.replay(mockEnv);
+    return mockEnv;
+  }
+
+  public void testGetClassMocks() throws IOException, CannotCompileException {
+    List<Class<?>> classesToMock = new ArrayList<Class<?>>();
+    classesToMock.add(TestCase.class);
+    List<String> expectedMocks =
+        new ArrayList<String>(Arrays.asList(new String[] {
+            "genmocks." + TestCase.class.getName() + "DelegateInterface",
+            "genmocks." + TestCase.class.getName() + "DelegateSubclass"}));
+    Set<GeneratedClassFile> mockedClasses =
+        getProcessor().getClassMocks(classesToMock, true);
+
+    assertEquals(2, mockedClasses.size());
+    for (GeneratedClassFile clazz : mockedClasses) {
+      assertTrue(expectedMocks.contains(clazz.getClassName()));
+      expectedMocks.remove(clazz.getClassName());
+    }
+  }
+
+  public void testWriteMocks() throws IOException, CannotCompileException {
+    List<Class<?>> classesToMock = new ArrayList<Class<?>>();
+    classesToMock.add(TestCase.class);
+    Set<GeneratedClassFile> mockedClassesSet =
+        getProcessor().getClassMocks(classesToMock, true);
+    ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+    getProcessor(getMockProcessingEnvironment(getMockFiler(getMockFileObject(outputStream))))
+        .writeMocks(mockedClassesSet);
+
+    String output = new String(outputStream.toByteArray());
+    for (GeneratedClassFile mockClass : mockedClassesSet) {
+      String expected = new String(mockClass.getContents());
+      assertTrue(output.contains(expected));
+      output = output.replace(expected, "");
+    }
+    assertEquals(0, output.length());
+  }
+
+  public void testProcess() {
+    assertFalse(getProcessor().process(null,
+        getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class))));
+    assertFalse(getProcessor().process(null,
+        getMockRoundEnvironment(getAnnotatedElementsSet(TestCase.class), true)));
+  }
+
+  public void testFindClassesToMock() {
+    Set<? extends Element> annotatedElements = getAnnotatedElementsSet(Set.class, TestCase.class);
+    List<Class<?>> classesList = getProcessor().findClassesToMock(annotatedElements);
+
+    assertEquals(annotatedElements.size(), classesList.size());
+    assertTrue(classesList.contains(Set.class));
+    assertTrue(classesList.contains(TestCase.class));
+  }
+}