diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 3f7dbaf..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2011 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT 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)
-
-# Include all the java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_SDK_VERSION := 14
-
-# The name of the jar file to create.
-LOCAL_MODULE := littlemock
-
-# Build a static jar file.
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/COPYING b/COPYING
deleted file mode 100644
index d645695..0000000
--- a/COPYING
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 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/CleanSpec.mk b/CleanSpec.mk
deleted file mode 100644
index b84e1b6..0000000
--- a/CleanSpec.mk
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright (C) 2007 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-#
-
-# If you don't need to do a full clean build but would like to touch
-# a file or delete some intermediate files, add a clean step to the end
-# of the list.  These steps will only be run once, if they haven't been
-# run before.
-#
-# E.g.:
-#     $(call add-clean-step, touch -c external/sqlite/sqlite3.h)
-#     $(call add-clean-step, rm -rf $(PRODUCT_OUT)/obj/STATIC_LIBRARIES/libz_intermediates)
-#
-# Always use "touch -c" and "rm -f" or "rm -rf" to gracefully deal with
-# files that are missing or have been moved.
-#
-# Use $(PRODUCT_OUT) to get to the "out/target/product/blah/" directory.
-# Use $(OUT_DIR) to refer to the "out" directory.
-#
-# If you need to re-do something that's already mentioned, just copy
-# the command and add it to the bottom of the list.  E.g., if a change
-# that you made last week required touching a file and a change you
-# made today requires touching the same file, just copy the old
-# touch step and add it to the end of the list.
-#
-# ************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
-# ************************************************
-
-# For example:
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/APPS/AndroidTests_intermediates)
-#$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/core_intermediates)
-#$(call add-clean-step, find $(OUT_DIR) -type f -name "IGTalkSession*" -print0 | xargs -0 rm -f)
-#$(call add-clean-step, rm -rf $(PRODUCT_OUT)/data/*)
-
-# ************************************************
-# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
-# ************************************************
diff --git a/MODULE_LICENSE_APACHE2 b/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index d645695..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,202 +0,0 @@
-
-                                 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/README b/README
deleted file mode 100644
index 86b8be6..0000000
--- a/README
+++ /dev/null
@@ -1,17 +0,0 @@
-This folder contains the littlemock library.
-
-The latest version of littlemock can be found at this url:
-    http://code.google.com/p/littlemock
-
-Version: r3
-License: Apache 2.0
-
-Description:
-Mocking framework. Looks very like Mockito (see http://mockito.org).
-Has a number of restrictions.
-Can mock concrete classes, requires dexmaker.jar on classpath.
-
-Local Modifications:
-- Change to AppDataDirGuesser to handle the new class loader toString
-  format introduced in JB.
-
diff --git a/src/com/google/testing/littlemock/AppDataDirGuesser.java b/src/com/google/testing/littlemock/AppDataDirGuesser.java
deleted file mode 100644
index 254ed7e..0000000
--- a/src/com/google/testing/littlemock/AppDataDirGuesser.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2011 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.testing.littlemock;
-
-import java.io.File;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Utility class for helping guess the application data directory.
- */
-public class AppDataDirGuesser {
-
-  /** A single default instance of app data dir guesser, for overriding if you really need to. */
-  private static volatile AppDataDirGuesser sInjectableInstance = new AppDataDirGuesser();
-
-  public static void setInstance(AppDataDirGuesser instance) {
-    sInjectableInstance = instance;
-  }
-
-  public static AppDataDirGuesser getsInstance() {
-    return sInjectableInstance;
-  }
-
-  public File guessSuitableDirectoryForGeneratedClasses() {
-    try {
-      ClassLoader classLoader = AppDataDirGuesser.class.getClassLoader();
-      // Check that we have an instance of the PathClassLoader.
-      Class<?> clazz = Class.forName("dalvik.system.PathClassLoader");
-      clazz.cast(classLoader);
-      // Use the toString() method to calculate the data directory.
-      String pathFromThisClassLoader =
-          getPathFromPathClassLoader(classLoader, clazz);
-      File[] results = guessPath(pathFromThisClassLoader);
-      if (results.length > 0) {
-        return results[0];
-      }
-    } catch (ClassCastException e) {
-      // Fall through, we will return null.
-    } catch (ClassNotFoundException e) {
-      // Fall through, we will return null.
-    }
-    return null;
-  }
-
-  private String getPathFromPathClassLoader(
-      ClassLoader classLoader, Class<?> pathClassLoaderClass) {
-    // Prior to ICS, we can simply read the "path" field of the
-    // PathClassLoader.
-    try {
-      Field pathField = pathClassLoaderClass.getDeclaredField("path");
-      pathField.setAccessible(true);
-      return (String) pathField.get(classLoader);
-    } catch (NoSuchFieldException e) {
-      // Ignore and fall back on parsing the output of toString below
-    } catch (IllegalAccessException e) {
-      // Ignore and fall back on parsing the output of toString below
-    } catch (ClassCastException e) {
-      // Ignore and fall back on parsing the output of toString below
-    }
-
-    // Parsing toString() method: yuck.  But no other way to get the path.
-    // Strip out the bit between square brackets, that's our path.
-    String result = classLoader.toString();
-    int index = result.lastIndexOf('[');
-    result = (index == -1) ? result : result.substring(index + 1);
-    index = result.indexOf(']');
-    return (index == -1) ? result : result.substring(0, index);
-  }
-
-  // @VisibleForTesting
-  File[] guessPath(String input) {
-    List<File> results = new ArrayList<File>();
-    for (String potential : splitPathList(input)) {
-      if (!potential.startsWith("/data/app/")) {
-        continue;
-      }
-      int start = "/data/app/".length();
-      int end = potential.lastIndexOf(".apk");
-      if (end != potential.length() - 4) {
-        continue;
-      }
-      int dash = potential.indexOf("-");
-      if (dash != -1) {
-        end = dash;
-      }
-      String packageName = potential.substring(start, end);
-      File dataDir = new File("/data/data/" + packageName);
-      if (isWriteableDirectory(dataDir)) {
-        File cacheDir = new File(dataDir, "cache");
-        if (fileOrDirExists(cacheDir) || makeDirectory(cacheDir)) {
-          if (isWriteableDirectory(cacheDir)) {
-            results.add(cacheDir);
-          }
-        }
-      }
-    }
-
-    return results.toArray(new File[results.size()]);
-  }
-
-  // @VisibleForTesting
-  static String[] splitPathList(String input) {
-    String trimmed = input;
-    if (input.startsWith("dexPath=")) {
-      int start = "dexPath=".length();
-      int end = input.indexOf(',');
-
-      trimmed = (end == -1) ? input.substring(start) :
-          input.substring(start, end);
-    }
-
-    return trimmed.split(":");
-  }
-
-  // @VisibleForTesting
-  boolean fileOrDirExists(File file) {
-      return file.exists();
-  }
-
-  // @VisibleForTesting
-  boolean makeDirectory(File file) {
-      return file.mkdir();
-  }
-
-  // @VisibleForTesting
-  boolean isWriteableDirectory(File file) {
-    return file.isDirectory() && file.canWrite();
-  }
-}
diff --git a/src/com/google/testing/littlemock/ArgumentCaptor.java b/src/com/google/testing/littlemock/ArgumentCaptor.java
deleted file mode 100644
index ff75246..0000000
--- a/src/com/google/testing/littlemock/ArgumentCaptor.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright 2011 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.testing.littlemock;
-
-import java.util.List;
-
-/**
- * Simple capture object for use in tests.
- *
- * @author hugohudson@gmail.com (Hugo Hudson)
- *
- * @param <T> the type we are going to capture
- */
-public interface ArgumentCaptor<T extends Object> extends LittleMock.ArgumentMatcher {
-  /** Gets the last value captured, or null if no value has been captured. */
-  public T getValue();
-
-  /** Gets the list of all values that have been captured. */
-  public List<T> getAllValues();
-
-  /** Use this argument captor to perform the capture. */
-  public T capture();
-
-}
diff --git a/src/com/google/testing/littlemock/Behaviour.java b/src/com/google/testing/littlemock/Behaviour.java
deleted file mode 100644
index f298285..0000000
--- a/src/com/google/testing/littlemock/Behaviour.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright 2011 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.testing.littlemock;
-
-/**
- * An action to be performed, yet to be attached to a method call.
- *
- * @author hugohudson@gmail.com (Hugo Hudson)
- */
-public interface Behaviour {
-  /** Attaches the given behaviour to the next method call of this mock. */
-  public <T> T when(T mock);
-}
diff --git a/src/com/google/testing/littlemock/Captor.java b/src/com/google/testing/littlemock/Captor.java
deleted file mode 100644
index 4fde58b..0000000
--- a/src/com/google/testing/littlemock/Captor.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 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.testing.littlemock;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Used to automatically inject a {@link ArgumentCaptor} object for use in your tests.
- *
- * <p>Just annotate your capture field on your test as follows:
- * <pre>
- *   &#64;Captor private ArgumentCaptor&lt;String&gt; mCaptureString;
- * </pre>
- *
- * <p>Then when the {@link LittleMock#initMocks(Object)} method is called (which should be
- * done in your setUp() call, or in a test base class) all your capture objects will be
- * automatically constructed.
- *
- * @author hugohudson@gmail.com (Hugo Hudson)
- */
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Captor {
-}
diff --git a/src/com/google/testing/littlemock/LittleMock.java b/src/com/google/testing/littlemock/LittleMock.java
deleted file mode 100644
index 140f853..0000000
--- a/src/com/google/testing/littlemock/LittleMock.java
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright 2011 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.testing.littlemock;
-
-import java.io.File;
-import java.io.ObjectInputStream;
-import java.io.ObjectStreamClass;
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.atomic.AtomicReference;
-
-/**
- * Very lightweight and simple mocking framework, inspired by Mockito, http://mockito.org.
- *
- * <p>It supports only a <b>small subset</b> of the APIs provided by Mockito and other mocking
- * frameworks.
- *
- * <p>This project was originally designed to be lightweight and suitable for platforms that don't
- * support dynamic class generation, for example Android.  Since the release of the open
- * source dexmaker project http://code.google.com/p/dexmaker/ we can now mock concrete classes
- * too.
- *
- * <p>Here is an example of how to use the framework.
- *
- * <p>Suppose that we have this interface:
- * <pre>
- *     public interface Foo {
- *       public String aString(int input);
- *       public void doSomething();
- *     }
- * </pre>
- *
- * <p>Then stubbing out mocks works as follows:
- * <pre>
- *     Foo mockFoo = mock(Foo.class);  // Create the mock.
- *     doReturn("hello").when(mockFoo).aString(anyInt());  // Stub the mock to return "hello".
- *     doThrow(new IOException("oh noes")).when(mockFoo).doSomething();
- *     assertEquals("hello", mockFoo.aString(5));  // Use the mock - performs as expected.
- *     mockFoo.doSomething();  // This will throw an IOException.
- * </pre>
- *
- * <p>You can verify in the 'natural place', after the method call has happened, like this:
- * <pre>
- *     Foo mockFoo = mock(Foo.class);
- *     assertEquals(null, mockFoo.aString(6));  // Unstubbed method calls return a sensible default.
- *     verify(mockFoo).aString(6);  // This will pass, aString() was called once.
- *     verify(mockFoo, never()).doSomething();  // This will pass, doSomething was never called.
- *     verify(mockFoo, times(3)).aString(anyInt());  // This will fail, was called once only.
- * </pre>
- *
- * <p>The documentation is still incomplete.  You can look at the {@link LittleMockTest} class and
- * its unit tests - since they tell you exactly what operations are supported and how to use them.
- *
- * <p>The reasons I much prefer Mockito's approach to the one of EasyMock are as follows:
- * <ul>
- *   <li>No need to remember to put your mocks in replay mode.</li>
- *   <li>No need to remember to call verify, a dangerous source of false-positive tests or
- *   alternatively over-specified tests.</li>
- *   <li>Much less over-specification: only verify what you actually care about.</li>
- *   <li>Which in turn leads to better separated tests, each test verifying only a part of the
- *   desired behaviour.</li>
- *   <li>Which also leads to less fragile tests, where adding another method call on your
- *   dependencies doesn't break unrelated tests.</li>
- *   <li>Simpler sharing of common setup method with specific tests overridding individual
- *   behavious however they want to, only the most recent stubbed call is the one that counts.</li>
- *   <li>More natural order for tests: set up stubs, execute tests, verify that it worked.</li>
- *   <li>More unified syntax that doesn't require special case for differences between void method
- *   calls and method calls that return a value.</li>
- * </ul>
- *
- * <p>There were enough reasons that I wanted to give Mockito a try.  It didn't work on Android
- * because of issues with class generation.  So I looked at the documentation and examples page and
- * added tests for all the examples, and then implemented the this framework.  I should stress that
- * this is a clean-room implementation, and as such it's possible that there are a couple of methods
- * that don't work in the same way as Mockito's implementation.  Where that is the case I think we
- * should fix once we discover them.  There is also some functionality missing, but it will be added
- * in due course.
- *
- * <p>Over time, the API has diverged slightly from the one of Mockito, as I have added APIs that I
- * found convenient but that did not have an equivalent in Mockite itself.  For anything that has an
- * equivalent in Mockito I tried to keep the same name and syntax, to make it easier to transition
- * between using one framework to using the other, e.g., when developing both an Android application
- * using this framework and a desktop application using Mockito.
- *
- * @author hugohudson@gmail.com (Hugo Hudson)
- */
-/*@NotThreadSafe*/
-public class LittleMock {
-  /** Generates a {@link Behaviour} suitable for void methods. */
-  public static Behaviour doNothing() { return doReturn(null); }
-
-  /** Generates a {@link Behaviour} that returns the given result. */
-  public static <T> Behaviour doReturn(final T result) {
-    return new BehaviourImpl(new Action() {
-      @Override public T doAction(Method method, Object[] args) { return result; }
-      @Override public Class<?> getReturnType() {
-        return (result == null) ? null : result.getClass();
-      }
-    });
-  }
-
-  /**
-   * Gets a {@link Behaviour} that will execute the given {@link Callable} and return its result.
-   */
-  public static <T> Behaviour doAnswer(final Callable<T> callable) {
-    return new BehaviourImpl(new Action() {
-      @Override
-      public T doAction(Method method, Object[] args) throws Throwable { return callable.call(); }
-      @Override
-      public Class<?> getReturnType() { return null; }
-    });
-  }
-
-  /** Returns a {@link Behaviour} that throws the given {@link Throwable}. */
-  public static <T extends Throwable> Behaviour doThrow(final T exception) {
-    return new BehaviourImpl(new Action() {
-      @Override
-      public Object doAction(Method method, Object[] args) throws Throwable { throw exception; }
-      @Override
-      public Class<?> getReturnType() { return null; }
-    });
-  }
-
-  /** Begins a verification step on a mock: the next method invocation on that mock will verify. */
-  public static <T> T verify(T mock, CallCount howManyTimes) {
-    return verify(mock, howManyTimes, null);
-  }
-
-  private static final class OrderChecker {
-    private MethodCall mLastCall;
-
-    public void checkOrder(List<MethodCall> calls, String fieldName) {
-      MethodCall lastTrial = null;
-      for (MethodCall trial : calls) {
-        if (mLastCall == null || mLastCall.mInvocationOrder < trial.mInvocationOrder) {
-          mLastCall = trial;
-          return;
-        }
-        lastTrial = trial;
-      }
-      fail(formatFailedVerifyOrderMessage(mLastCall, lastTrial, fieldName));
-    }
-
-    private String formatFailedVerifyOrderMessage(MethodCall lastCall, MethodCall thisCall,
-        String fieldName) {
-      StringBuffer sb = new StringBuffer();
-      sb.append("\nCall to:");
-      appendDebugStringForMethodCall(sb, thisCall.mMethod, thisCall.mElement, fieldName, false);
-      sb.append("\nShould have happened after:");
-      appendDebugStringForMethodCall(sb, lastCall.mMethod, lastCall.mElement, fieldName, false);
-      sb.append("\nBut the calls happened in the wrong order");
-      sb.append("\n");
-      return sb.toString();
-    }
-  }
-
-  private static <T> T verify(T mock, CallCount howManyTimes, OrderChecker orderCounter) {
-    if (howManyTimes == null) {
-      throw new IllegalArgumentException("Can't pass null for howManyTimes parameter");
-    }
-    DefaultInvocationHandler handler = getHandlerFrom(mock);
-    checkState(handler.mHowManyTimes == null, "Unfinished verify() statements");
-    checkState(handler.mOrderCounter == null, "Unfinished verify() statements");
-    checkState(handler.mStubbingAction == null, "Unfinished stubbing statements");
-    checkNoMatchers();
-    handler.mHowManyTimes = howManyTimes;
-    handler.mOrderCounter = orderCounter;
-    sUnfinishedCallCounts.add(howManyTimes);
-    return handler.<T>getVerifyingMock();
-  }
-
-  /** The list of outstanding calls to verify() that haven't finished, used to check for errors. */
-  private static List<CallCount> sUnfinishedCallCounts = new ArrayList<CallCount>();
-
-  /** The list of outstanding calls to when() that haven't finished, used to check for errors. */
-  private static List<Action> sUnfinishedStubbingActions = new ArrayList<Action>();
-
-  /** Begins a verification step for exactly one method call. */
-  public static <T> T verify(T mock) { return verify(mock, times(1)); }
-
-  /** Assert that no method calls at all happened on these mocks. */
-  public static void verifyZeroInteractions(Object... mocks) {
-    checkNoMatchers();
-    for (Object mock : mocks) {
-      List<MethodCall> mMethodCalls = getHandlerFrom(mock).mRecordedCalls;
-      expect(mMethodCalls.isEmpty(), "Mock expected zero interactions, had " + mMethodCalls);
-    }
-  }
-
-  /** Assert that there are no unverified method calls on these mocks. */
-  public static void verifyNoMoreInteractions(Object... mocks) {
-    StackTraceElement callSite = new Exception().getStackTrace()[1];
-    for (Object mock : mocks) {
-      verifyNoMoreInteractions(mock, callSite);
-    }
-  }
-
-  /** Check that there are no unverified actions on the given mock. */
-  private static void verifyNoMoreInteractions(Object mock, StackTraceElement callSite) {
-    checkNoMatchers();
-    DefaultInvocationHandler handlerFrom = getHandlerFrom(mock);
-    List<MethodCall> unverifiedCalls = new ArrayList<MethodCall>();
-    for (MethodCall method : handlerFrom.mRecordedCalls) {
-      if (!method.mWasVerified) {
-        unverifiedCalls.add(method);
-      }
-    }
-    if (unverifiedCalls.size() > 0) {
-      StringBuffer sb = new StringBuffer();
-      sb.append("\nWe found these unverified calls:");
-      for (MethodCall method : unverifiedCalls) {
-        appendDebugStringForMethodCall(sb, method.mMethod,
-            method.mElement, handlerFrom.mFieldName, false);
-      }
-      sb.append("\n\nAfter final interaction was verified:\n");
-      sb.append("  at ").append(callSite).append("\n");
-      throw new AssertionError(sb.toString());
-    }
-  }
-
-  /** Creates a {@link CallCount} that matches exactly the given number of calls. */
-  public static CallCount times(long n) { return new CallCount(n, n); }
-
-  /** Claims that the verified call must happen before the given timeout. */
-  public static Timeout timeout(long timeoutMillis) {
-    return new Timeout(1, 1, timeoutMillis);
-  }
-
-/** Creates a {@link CallCount} that only matches if the method was never called. */
-  public static CallCount never() { return new CallCount(0, 0); }
-
-  /** Creates a {@link CallCount} that matches at least one method call. */
-  public static CallCount atLeastOnce() { return new CallCount(1, Long.MAX_VALUE); }
-
-  /** Creates a {@link CallCount} that matches any number of method calls, including none at all. */
-  public static CallCount anyTimes() { return new CallCount(0, Long.MAX_VALUE); }
-
-  /** Creates a {@link CallCount} that matches at least the given number of calls. */
-  public static CallCount atLeast(long n) { return new CallCount(n, Long.MAX_VALUE); }
-
-  /** Creates a {@link CallCount} that matches up to the given number of calls but no more. */
-  public static CallCount atMost(long n) { return new CallCount(0, n); }
-
-  /** Creates a {@link CallCount} that matches any number of calls between the two given bounds. */
-  public static CallCount between(long lower, long upper) { return new CallCount(lower, upper); }
-
-  /**
-   * Creates an argument matcher that matches any object, don't use for primitives.
-   * <p>
-   * <b>Note</b>: This does not enforce that the object is of type {@code T}; use
-   * {@link #isA(Class)} to do that.
-   */
-  public static <T> T anyObject() { return LittleMock.<T>addMatcher(new MatchAnything(), null); }
-
-  /** Generates an argument matcher that matches any string. */
-  public static String anyString() { return isA(String.class); }
-
-  /** Generates an argument matcher that matches any int. */
-  public static int anyInt() { return addMatcher(new MatchAnything(), 0); }
-
-  /** Generates an argument matcher that matches any float. */
-  public static float anyFloat() { return addMatcher(new MatchAnything(), 0f); }
-
-  /** Generates an argument matcher that matches any double. */
-  public static double anyDouble() { return addMatcher(new MatchAnything(), 0.0); }
-
-  /** Generates an argument matcher that matches any boolean. */
-  public static boolean anyBoolean() { return addMatcher(new MatchAnything(), false); }
-
-  /** Generates an argument matcher that matches any short. */
-  public static short anyShort() { return addMatcher(new MatchAnything(), (short) 0); }
-
-  /** Generates an argument matcher that matches any char. */
-  public static char anyChar() { return addMatcher(new MatchAnything(), '\u0000'); }
-
-  /** Generates an argument matcher that matches any long. */
-  public static long anyLong() { return addMatcher(new MatchAnything(), 0L); }
-
-  /** Generates an argument matcher that matches any byte. */
-  public static byte anyByte() { return addMatcher(new MatchAnything(), (byte) 0); }
-
-  /** Generates an argument matcher that matches exactly this value. */
-  public static <T> T eq(final T expected) {
-    return addMatcher(new ArgumentMatcher() {
-      @Override
-      public boolean matches(Object value) {
-        return areEqual(expected, value);
-      }
-    }, expected);
-  }
-
-  /** An argument matcher that matches any value of the given type or a subtype thereof. */
-  public static <T> T isA(final Class<T> clazz) {
-    return LittleMock.<T>addMatcher(new ArgumentMatcher() {
-      @Override
-      public boolean matches(Object value) {
-        return value == null || clazz.isAssignableFrom(value.getClass());
-      }
-    }, null);
-  }
-
-  /**
-   * Injects fields annotated with {@link Mock} with a newly created mock, and those
-   * annotated with {@link Captor} with a suitable capture object.
-   *
-   * <p>This operation is recursive, and travels up the class hierarchy, in order to set all
-   * suitably annotated fields.
-   */
-  public static void initMocks(Object instance) throws Exception {
-    injectMocksForClass(instance, instance.getClass());
-  }
-
-  /** Recurse up the class hierarchy injecting mocks as we go, stopping when we reach Object. */
-  private static void injectMocksForClass(Object instance, Class<?> clazz)
-      throws Exception {
-    if (clazz.equals(Object.class)) {
-      return;
-    }
-    for (Field field : clazz.getDeclaredFields()) {
-      if (field.getAnnotation(Mock.class) != null) {
-        setField(field, instance, mock(field.getType(), field.getName()));
-      } else if (field.getAnnotation(Captor.class) != null) {
-        setField(field, instance, createCaptor());
-      }
-    }
-    injectMocksForClass(instance, clazz.getSuperclass());
-  }
-
-  /**
-   * Creates a correctly typed {@link ArgumentCaptor} , it's easier to use
-   * {@link #initMocks(Object)}.
-   */
-  public static <T> ArgumentCaptor<T> createCaptor() {
-    return new ArgumentCaptorImpl<T>();
-  }
-
-  /**
-   * Create a correctly typed ArgumentCaptor that also works for primitive types.
-   * For example, to capture an int, use
-   * <code>ArgumentCaptor<Integer> c = createCaptor(Integer.class);</code>
-   */
-  public static <T> ArgumentCaptor<T> createCaptor(Class<T> clazz) {
-    return new ArgumentCaptorImpl<T>(clazz);
-  }
-
-  /** Implementation of the {@link ArgumentCaptor} interface. */
-  private static class ArgumentCaptorImpl<T extends Object> implements ArgumentCaptor<T> {
-    private final ArrayList<T> mAllValues = new ArrayList<T>();
-    private T mValue;
-    private Class<T> mClass;
-
-    private ArgumentCaptorImpl() {
-        mClass = null;
-    }
-
-    private ArgumentCaptorImpl(Class<T> clazz) {
-        mClass = clazz;
-    }
-
-    public void setValue(T value) {
-      mValue = value;
-      mAllValues.add(mValue);
-    }
-
-    @Override
-    public T getValue() {
-      return mValue;
-    }
-
-    @Override
-    public List<T> getAllValues() {
-      return mAllValues;
-    }
-
-    @Override
-    public T capture() {
-      if (mClass != null) {
-        if (Integer.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Integer>addMatcher(this, 0);
-        }
-        if (Float.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Float>addMatcher(this, 0f);
-        }
-        if (Double.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Double>addMatcher(this, 0.0);
-        }
-        if (Boolean.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Boolean>addMatcher(this, false);
-        }
-        if (Short.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Short>addMatcher(this, (short) 0);
-        }
-        if (Character.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Character>addMatcher(this, '\u0000');
-        }
-        if (Long.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Long>addMatcher(this, 0L);
-        }
-        if (Byte.class.isAssignableFrom(mClass)) {
-          return (T) LittleMock.<Byte>addMatcher(this, (byte) 0);
-        }
-      }
-      return LittleMock.<T>addMatcher(this, null);
-    }
-
-
-    @Override
-    public boolean matches(Object value) {
-      // A capture always matches any argument.
-      // This is so that verify(mMock).someMethod(capture(mCapture)) will match any and all calls
-      // to someMethod() and we will capture the values into mCapture.
-      return true;
-    }
-  }
-
-  /**
-   * Creates a mock, more easily done via the {@link #initMocks(Object)} method.
-   *
-   * <p>Also if you use this method to create your mock, the field in the error messages will
-   * be named the same as your class passed in, you only get the actual field name if you
-   * use the annotation.
-   *
-   * @throws IllegalArgumentException if the class you pass in is null
-   */
-  public static <T> T mock(Class<T> clazz) {
-    if (clazz == null) {
-      throw new IllegalArgumentException("Class to mock was null");
-    }
-    return mock(clazz, getDefaultFieldNameFor(clazz));
-  }
-
-  /** Creates a mock, more easily done via the {@link #initMocks(Object)} method. */
-  @SuppressWarnings("unchecked")
-  private static <T> T mock(Class<T> clazz, String fieldName) {
-    return (T) createProxy(clazz, new DefaultInvocationHandler(clazz, fieldName));
-  }
-
-  /** Pick a suitable name for a field of the given clazz. */
-  private static String getDefaultFieldNameFor(Class<?> clazz) {
-    return clazz.getSimpleName().substring(0, 1).toLowerCase()
-        + clazz.getSimpleName().substring(1);
-  }
-
-  /** Clears out the expectations on these mocks. */
-  public static void reset(Object... mocks) {
-    for (Object mock : mocks) {
-      getHandlerFrom(mock).reset();
-    }
-  }
-
-  /** Use this in tear down to check for programming errors. */
-  public static void checkForProgrammingErrorsDuringTearDown() {
-    checkNoMatchers();
-    checkNoUnfinishedCalls(sUnfinishedCallCounts, "verify()");
-    checkNoUnfinishedCalls(sUnfinishedStubbingActions, "stubbing");
-  }
-
-  /** Helper function to check that there are no verify or stubbing commands outstanding. */
-  private static void checkNoUnfinishedCalls(List<?> list, String type) {
-    if (!list.isEmpty()) {
-      list.clear();
-      throw new IllegalStateException("Unfinished " + type + " statements");
-    }
-  }
-
-  /** Implementation of {@link Behaviour}. */
-  private static class BehaviourImpl implements Behaviour {
-    private final Action mAction;
-
-    private BehaviourImpl(Action action) {
-      mAction = action;
-    }
-
-    @Override
-    public <T> T when(T mock) {
-      DefaultInvocationHandler handler = getHandlerFrom(mock);
-      checkState(handler.mHowManyTimes == null, "Unfinished verify() statements");
-      checkState(handler.mOrderCounter == null, "Unfinished verify() statements");
-      checkState(handler.mStubbingAction == null, "Unfinished stubbing statements");
-      handler.mStubbingAction = mAction;
-      sUnfinishedStubbingActions.add(mAction);
-      return handler.<T>getStubbingMock();
-    }
-  }
-
-  /**
-   * The static list of argument matchers, used in the next method call to the mock.
-   *
-   * <p>In order to support the syntax like this: verify(mFoo).someMethod(anyInt()), it is
-   * required that the anyInt() method store the value somewhere for use when the someMethod
-   * is invoked.  That somewhere has to be static.  I don't like it any more than you do.
-   *
-   * <p>The same goes for anything that is passed into the someMethod as an argument - be it
-   * a capture(mCaptureString) or eq(5) or whatever.
-   *
-   * <p>Avoiding the use of statics requires that we change the syntax of the verify statement,
-   * and I can't think of an elegant way of doing it, and in any case I really like the current
-   * syntax, so for now a static variable it is.
-   *
-   * <p>This match arguments list should contain either zero elements (the next method call will
-   * not use any argument matchers) or it should contain exactly one argument matcher for
-   * every argument being passed to the next method call.  You can't mix argument matchers and
-   * raw values.
-   */
-  private static final List<ArgumentMatcher> sMatchArguments = new ArrayList<ArgumentMatcher>();
-
-  /** Global invocation order of every mock method call. */
-  private static final AtomicLong sGlobalInvocationOrder = new AtomicLong();
-
-  /** Encapsulates a single call of a method with associated arguments. */
-  private static class MethodCall {
-    /** The method call. */
-    private final Method mMethod;
-    /** The arguments provided at the time the call happened. */
-    private final Object[] mArgs;
-    /** The order in which this method call was invoked. */
-    private final long mInvocationOrder;
-    /** The line from the test that invoked the handler to create this method call. */
-    private final StackTraceElement mElement;
-    /** Keeps track of method calls that have been verified, for verifyNoMoreInteractions(). */
-    public boolean mWasVerified = false;
-
-    public MethodCall(Method method, StackTraceElement element, Object[] args) {
-      mMethod = method;
-      mElement = element;
-      mArgs = args;
-      mInvocationOrder = sGlobalInvocationOrder.getAndIncrement();
-    }
-
-    public boolean argsMatch(Object[] args) {
-      return Arrays.equals(mArgs, args);
-    }
-
-    @Override
-    public String toString() {
-      return "MethodCall [method=" + mMethod + ", args=" + Arrays.toString(mArgs) + "]";
-    }
-  }
-
-  private static boolean areMethodsSame(Method first, Method second) {
-    return areEqual(first.getDeclaringClass(), second.getDeclaringClass()) &&
-        areEqual(first.getName(), second.getName()) &&
-        areEqual(first.getReturnType(), second.getReturnType()) &&
-        Arrays.equals(first.getParameterTypes(), second.getParameterTypes());
-  }
-
-  private static boolean areEqual(Object a, Object b) {
-    if (a == null) {
-      return b == null;
-    }
-    return a.equals(b);
-  }
-
-  /**
-   * Magically handles the invoking of method calls.
-   *
-   * <p>This object is in one of three states, default (where invoking methods returns default
-   * values and records the call), verifying (where invoking method calls makes sure that those
-   * method calls happen with the supplied arguments or matchers) or stubbing (where the next method
-   * call tells us which arguments to match in order to perform the desired behaviour).
-   */
-  private static class DefaultInvocationHandler implements InvocationHandler {
-    private static Method sEqualsMethod;
-    private static Method sHashCodeMethod;
-    private static Method sToStringMethod;
-
-    static {
-      try {
-        sEqualsMethod = Object.class.getMethod("equals", Object.class);
-        sHashCodeMethod = Object.class.getMethod("hashCode");
-        sToStringMethod = Object.class.getMethod("toString");
-      } catch (SecurityException e) {
-        // Should never happen.
-        throw new RuntimeException("Your JVM/classloader is broken", e);
-      } catch (NoSuchMethodException e) {
-        // Should never happen.
-        throw new RuntimeException("Your JVM/classloader is broken", e);
-      }
-    }
-
-    /** The class of the mocked objects. */
-    private final Class<?> mClazz;
-    /** The field name in which the mock is assigned. */
-    private final String mFieldName;
-
-    /** The list of method calls executed on the mock. */
-    private List<MethodCall> mRecordedCalls = new CopyOnWriteArrayList<MethodCall>();
-    /** The list of method calls that were stubbed out and their corresponding actions. */
-    private List<StubbedCall> mStubbedCalls = new CopyOnWriteArrayList<StubbedCall>();
-
-    /**
-     * The number of times a given call should be verified.
-     *
-     * <p>It is not null when in the verification state, and it is actually used to determine if we
-     * are in the verification state.
-     *
-     * <p>It is reset to null once the verification has occurred.
-     */
-    private CallCount mHowManyTimes = null;
-    private OrderChecker mOrderCounter = null;
-
-    /**
-     * The action to be associated with the stubbed method.
-     *
-     * <p>It is not null when in the stubbing state, and it is actually used to determine if we are
-     * in the stubbing state.
-     */
-    private Action mStubbingAction = null;
-
-    /** Dynamic proxy used to verify calls against this mock. */
-    private final Object mVerifyingMock;
-
-    /** Dynamic proxy used to stub calls against this mock. */
-    private final Object mStubbingMock;
-
-    /**
-     * Creates a new invocation handler for an object.
-     *
-     * @param clazz the class the object belongs to
-     * @param fieldName The name to be used to refer to the object. This may either be the name of
-     *        the field this mock will be stored into (in case it uses @Mock) or a suitable name to
-     *        use to refer to the object in error messages, based on the name of the class itself.
-     */
-    public DefaultInvocationHandler(Class<?> clazz, String fieldName) {
-      mClazz = clazz;
-      mFieldName = fieldName;
-      mVerifyingMock = createVerifyingMock(clazz);
-      mStubbingMock = createStubbingMock(clazz);
-    }
-
-    // Safe if you call getHandlerFrom(mock).getVerifyingMock(), since this is guaranteed to be
-    // of the same type as mock itself.
-    @SuppressWarnings("unchecked")
-    public <T> T getVerifyingMock() {
-      return (T) mVerifyingMock;
-    }
-
-    // Safe if you call getHandlerFrom(mock).getStubbingMock(), since this is guaranteed to be
-    // of the same type as mock itself.
-    @SuppressWarnings("unchecked")
-    public <T> T getStubbingMock() {
-      return (T) mStubbingMock;
-    }
-
-    /** Used to check that we always stub and verify from the same thread. */
-    private AtomicReference<Thread> mCurrentThread = new AtomicReference<Thread>();
-
-    /** Check that we are stubbing and verifying always from the same thread. */
-    private void checkThread() {
-      Thread currentThread = Thread.currentThread();
-      mCurrentThread.compareAndSet(null, currentThread);
-      if (mCurrentThread.get() != currentThread) {
-        throw new IllegalStateException("Must always mock and stub from one thread only.  "
-            + "This thread: " + currentThread + ", the other thread: " + mCurrentThread.get());
-      }
-    }
-
-    /** Generate the dynamic proxy that will handle verify invocations. */
-    private Object createVerifyingMock(Class<?> clazz) {
-      return createProxy(clazz, new InvocationHandler() {
-        @Override
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-          checkThread();
-          expect(mHowManyTimes != null, "verifying mock doesn't know how many times");
-          try {
-            ArgumentMatcher[] matchers = checkClearAndGetMatchers(method);
-            StackTraceElement callSite = new Exception().getStackTrace()[2];
-            MethodCall methodCall = new MethodCall(method, callSite, args);
-            innerVerify(method, matchers, methodCall, proxy, callSite, mHowManyTimes, mOrderCounter);
-            return defaultReturnValue(method.getReturnType());
-          } finally {
-            sUnfinishedCallCounts.remove(mHowManyTimes);
-            mHowManyTimes = null;
-            mOrderCounter = null;
-          }
-        }
-      });
-    }
-
-    /** Generate the dynamic proxy that will handle stubbing invocations. */
-    private Object createStubbingMock(Class<?> clazz) {
-      return createProxy(clazz, new InvocationHandler() {
-        @Override
-        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-          checkThread();
-          expect(mStubbingAction != null, "stubbing mock doesn't know what action to perform");
-          try {
-            ArgumentMatcher[] matchers = checkClearAndGetMatchers(method);
-            StackTraceElement callSite = new Exception().getStackTrace()[2];
-            MethodCall methodCall = new MethodCall(method, callSite, args);
-            innerStub(method, matchers, methodCall, callSite, mStubbingAction);
-            return defaultReturnValue(method.getReturnType());
-          } finally {
-            sUnfinishedStubbingActions.remove(mStubbingAction);
-            mStubbingAction = null;
-          }
-        }
-      });
-    }
-
-    @Override
-    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-      StackTraceElement callSite = new Exception().getStackTrace()[2];
-      MethodCall methodCall = new MethodCall(method, callSite, args);
-      return innerRecord(method, args, methodCall, proxy, callSite);
-    }
-
-    /**
-     * Checks whether the given method is one of the special object methods that should not
-     * verified or stubbed.
-     * <p>
-     * If this is one of such methods, it throws an AssertionException.
-     *
-     * @param method the method to be checked
-     * @param operation the name of the operation, used for generating a helpful message
-     */
-    private void checkSpecialObjectMethods(Method method, String operation) {
-      if (areMethodsSame(method, sEqualsMethod)
-          || areMethodsSame(method, sHashCodeMethod)
-          || areMethodsSame(method, sToStringMethod)) {
-        fail("cannot " + operation + " call to " + method);
-      }
-    }
-
-    private void reset() {
-      mRecordedCalls.clear();
-      mStubbedCalls.clear();
-      mHowManyTimes = null;
-      mOrderCounter = null;
-      mStubbingAction = null;
-    }
-
-    private Object innerRecord(Method method, final Object[] args,
-            MethodCall methodCall, Object proxy, StackTraceElement callSite) throws Throwable {
-      if (areMethodsSame(method, sEqualsMethod)) {
-        // Use identify for equality, the default behavior on object.
-        return proxy == args[0];
-      } else if (areMethodsSame(method, sHashCodeMethod)) {
-        // This depends on the fact that each mock has its own DefaultInvocationHandler.
-        return hashCode();
-      } else if (areMethodsSame(method, sToStringMethod)) {
-        // This is used to identify this is a mock, e.g., in error messages.
-        return "Mock<" + mClazz.getName() + ">";
-      }
-      mRecordedCalls.add(methodCall);
-      for (StubbedCall stubbedCall : mStubbedCalls) {
-        if (areMethodsSame(stubbedCall.mMethodCall.mMethod, methodCall.mMethod)) {
-          if (stubbedCall.mMethodCall.argsMatch(methodCall.mArgs)) {
-            methodCall.mWasVerified = true;
-            return stubbedCall.mAction.doAction(method, args);
-          }
-        }
-      }
-      // If no stub is defined, return the default value.
-      return defaultReturnValue(method.getReturnType());
-    }
-
-    private void innerStub(Method method, final ArgumentMatcher[] matchers, MethodCall methodCall,
-        StackTraceElement callSite, final Action stubbingAction) {
-      checkSpecialObjectMethods(method, "stub");
-      checkThisActionCanBeUsedForThisMethod(method, stubbingAction, callSite);
-      if (matchers.length == 0) {
-        // If there are no matchers, then this is a simple stubbed method call with an action.
-        mStubbedCalls.add(0, new StubbedCall(methodCall, stubbingAction));
-        return;
-      }
-      // If there are matchers, then we need to make a new method call which matches only
-      // when all the matchers match.  Further, the action that method call needs to take
-      // is to first record the values into any captures that may be present, and only then
-      // proceed to execute the original action.
-      MethodCall matchMatchersMethodCall = new MethodCall(method, callSite, matchers) {
-        @Override
-        public boolean argsMatch(Object[] args) { return doMatchersMatch(matchers, args); }
-      };
-      Action setCapturesThenAction = new Action() {
-        @Override
-        public Object doAction(Method innerMethod, Object[] innerArgs) throws Throwable {
-          setCaptures(matchers, innerArgs);
-          return stubbingAction.doAction(innerMethod, innerArgs);
-        }
-        @Override
-        public Class<?> getReturnType() {
-          return stubbingAction.getReturnType();
-        }
-      };
-      mStubbedCalls.add(0, new StubbedCall(matchMatchersMethodCall, setCapturesThenAction));
-    }
-
-    private void checkThisActionCanBeUsedForThisMethod(Method method, final Action stubbingAction,
-        StackTraceElement callSite) {
-      Class<?> methodType = method.getReturnType();
-      Class<?> actionType = stubbingAction.getReturnType();
-      if (actionType == null) {
-        // We could not determine the type returned by this action at the time we
-        // created it. At this time we cannot check that the returned value is
-        // appropriate to the return type of the method.
-        // However, if the type is not correct, any actual invocation of the method
-        // will fail later on.
-        return;
-      }
-      if (!methodType.isAssignableFrom(actionType)) {
-        if (methodType.isPrimitive() &&
-            actionType.equals(PRIMITIVE_TO_BOXED_LOOKUP.get(methodType))) {
-          return;
-        }
-        StringBuffer sb = new StringBuffer();
-        sb.append("\nCan't return ").append(actionType.getSimpleName()).append(" from stub for:");
-        appendDebugStringForMethodCall(sb, method, callSite, mFieldName, true);
-        sb.append("\n");
-        throw new IllegalArgumentException(sb.toString());
-      }
-    }
-
-    private boolean doMatchersMatch(ArgumentMatcher[] matchers, Object[] args) {
-      for (int i = 0; i < matchers.length; ++i) {
-        if (!matchers[i].matches(args[i])) {
-          return false;
-        }
-      }
-      return true;
-    }
-
-    private void innerVerify(Method method, ArgumentMatcher[] matchers, MethodCall methodCall,
-        Object proxy, StackTraceElement callSite, CallCount callCount, OrderChecker orderCounter) {
-      checkSpecialObjectMethods(method, "verify");
-      List<MethodCall> calls = countMatchingInvocations(method, matchers, methodCall);
-      long callTimeout = callCount.getTimeout();
-      checkState(orderCounter == null || callTimeout == 0, "can't inorder verify with a timeout");
-      if (callTimeout > 0) {
-        long endTime = System.currentTimeMillis() + callTimeout;
-        while (!callCount.matches(calls.size())) {
-          try {
-            Thread.sleep(1);
-          } catch (InterruptedException e) {
-            fail("interrupted whilst waiting to verify");
-          }
-          if (System.currentTimeMillis() > endTime) {
-            fail(formatFailedVerifyMessage(methodCall, calls.size(), callTimeout, callCount));
-          }
-          calls = countMatchingInvocations(method, matchers, methodCall);
-        }
-      } else {
-        if (orderCounter != null) {
-            orderCounter.checkOrder(calls, mFieldName);
-        } else if (!callCount.matches(calls.size())) {
-          fail(formatFailedVerifyMessage(methodCall, calls.size(), 0, callCount));
-        }
-      }
-    }
-
-    private List<MethodCall> countMatchingInvocations(Method method, ArgumentMatcher[] matchers,
-        MethodCall methodCall) {
-      List<MethodCall> methodCalls = new ArrayList<MethodCall>();
-      for (MethodCall call : mRecordedCalls) {
-        if (areMethodsSame(call.mMethod, method)) {
-          if ((matchers.length > 0 && doMatchersMatch(matchers, call.mArgs)) ||
-              call.argsMatch(methodCall.mArgs)) {
-            setCaptures(matchers, call.mArgs);
-            methodCalls.add(call);
-            call.mWasVerified  = true;
-          }
-        }
-      }
-      return methodCalls;
-    }
-
-    private String formatFailedVerifyMessage(MethodCall methodCall, int total, long timeoutMillis,
-        CallCount callCount) {
-      StringBuffer sb = new StringBuffer();
-      sb.append("\nExpected ").append(callCount);
-      if (timeoutMillis > 0) {
-        sb.append(" within " + timeoutMillis + "ms");
-      }
-      sb.append(" to:");
-      appendDebugStringForMethodCall(sb, methodCall.mMethod,
-          methodCall.mElement, mFieldName, false);
-      sb.append("\n\n");
-      if (mRecordedCalls.size() == 0) {
-        sb.append("No method calls happened on this mock");
-      } else {
-        sb.append("Method calls that did happen:");
-        for (MethodCall recordedCall : mRecordedCalls) {
-          appendDebugStringForMethodCall(sb, recordedCall.mMethod,
-              recordedCall.mElement, mFieldName, false);
-        }
-      }
-      sb.append("\n");
-      return sb.toString();
-    }
-
-    /** All matchers that are captures will store the corresponding arg value. */
-    // This suppress warning means that I'm calling setValue with something that I can't promise
-    // is of the right type.  But I think it is unavoidable.  Certainly I could give a better
-    // error message than the class cast exception you'll get when you try to retrieve the value.
-    @SuppressWarnings("unchecked")
-    private void setCaptures(ArgumentMatcher[] matchers, Object[] args) {
-      for (int i = 0; i < matchers.length; ++i) {
-        if (matchers[i] instanceof ArgumentCaptorImpl) {
-          ArgumentCaptorImpl.class.cast(matchers[i]).setValue(args[i]);
-        }
-      }
-    }
-
-    /** An empty array of matchers, to optimise the toArray() call below. */
-    private static final ArgumentMatcher[] EMPTY_MATCHERS_ARRAY = new ArgumentMatcher[0];
-
-    /** Makes sure that we have the right number of MATCH_ARGUMENTS for the given method. */
-    private ArgumentMatcher[] checkClearAndGetMatchers(Method method) {
-      ArgumentMatcher[] matchers = sMatchArguments.toArray(EMPTY_MATCHERS_ARRAY);
-      sMatchArguments.clear();
-      if (matchers.length > 0 && method.getParameterTypes().length != matchers.length) {
-        throw new IllegalArgumentException("You can't mix matchers and regular objects.");
-      }
-      return matchers;
-    }
-  }
-
-  private static void appendDebugStringForMethodCall(StringBuffer sb, Method method,
-      StackTraceElement callSite, String fieldName, boolean showReturnType) {
-    sb.append("\n  ");
-    if (showReturnType) {
-      sb.append("(").append(method.getReturnType().getSimpleName()).append(") ");
-    }
-    sb.append(fieldName).append(".").append(method.getName()).append("(");
-    int i = 0;
-    for (Class<?> type : method.getParameterTypes()) {
-      if (++i > 1) {
-        sb.append(", ");
-      }
-      sb.append(type.getSimpleName());
-    }
-    sb.append(")\n  at ").append(callSite);
-  }
-
-  /** Call this function when you don't expect there to be any outstanding matcher objects. */
-  private static void checkNoMatchers() {
-    if (sMatchArguments.size() > 0) {
-      sMatchArguments.clear();
-      throw new IllegalStateException("You have outstanding matchers, must be programming error");
-    }
-  }
-
-  /** A pairing of a method call and an action to be performed when that call happens. */
-  private static class StubbedCall {
-    private final MethodCall mMethodCall;
-    private final Action mAction;
-
-    public StubbedCall(MethodCall methodCall, Action action) {
-      mMethodCall = methodCall;
-      mAction = action;
-    }
-
-    @Override
-    public String toString() {
-      return "StubbedCall [methodCall=" + mMethodCall + ", action=" + mAction + "]";
-    }
-  }
-
-  /** Represents an action to be performed as a result of a method call. */
-  private interface Action {
-    public Object doAction(Method method, Object[] arguments) throws Throwable;
-    /** The type of the action, or null if we can't determine the type at stub time. */
-    public Class<?> getReturnType();
-  }
-
-  /** Represents something capable of testing if it matches an argument or not. */
-  public interface ArgumentMatcher {
-    public boolean matches(Object value);
-  }
-
-  /** A matcher that matches any argument. */
-  private static class MatchAnything implements ArgumentMatcher {
-    @Override
-    public boolean matches(Object value) { return true; }
-  }
-
-  /** Encapsulates the number of times a method is called, between upper and lower bounds. */
-  private static class CallCount {
-    private long mLowerBound;
-    private long mUpperBound;
-
-    public CallCount(long lowerBound, long upperBound) {
-      mLowerBound = lowerBound;
-      mUpperBound = upperBound;
-    }
-
-    /** Tells us if this call count matches a desired count. */
-    public boolean matches(long total) {
-      return total >= mLowerBound && total <= mUpperBound;
-    }
-
-    /** Tells us how long we should block waiting for the verify to happen. */
-    public long getTimeout() {
-      return 0;
-    }
-
-    public CallCount setLowerBound(long lowerBound) {
-      mLowerBound = lowerBound;
-      return this;
-    }
-
-    public CallCount setUpperBound(long upperBound) {
-      mUpperBound = upperBound;
-      return this;
-    }
-
-    @Override
-    public String toString() {
-      if (mLowerBound == mUpperBound) {
-        return "exactly " + mLowerBound + plural(" call", mLowerBound);
-      } else {
-        return "between " + mLowerBound + plural(" call", mLowerBound) + " and " +
-            mUpperBound + plural(" call", mUpperBound);
-      }
-    }
-  }
-
-  /** Encapsulates adding number of times behaviour to a call count with timeout. */
-  public static final class Timeout extends CallCount {
-    private long mTimeoutMillis;
-
-    public Timeout(long lowerBound, long upperBound, long timeoutMillis) {
-      super(lowerBound, upperBound);
-      mTimeoutMillis = timeoutMillis;
-    }
-
-    @Override
-    public long getTimeout() {
-      return mTimeoutMillis;
-    }
-
-    public CallCount times(int times) { return setLowerBound(times).setUpperBound(times); }
-    public CallCount atLeast(long n) { return setLowerBound(n).setUpperBound(Long.MAX_VALUE); }
-    public CallCount atLeastOnce() { return setLowerBound(1).setUpperBound(Long.MAX_VALUE); }
-    public CallCount between(long n, long m) { return setLowerBound(n).setUpperBound(m); }
-  }
-
-  /** Helper method to add an 's' to a string iff the count is not 1. */
-  private static String plural(String prefix, long count) {
-    return (count == 1) ? prefix : (prefix + "s");
-  }
-
-  /** Helps us implement the eq(), any() and capture() and other methods on one line. */
-  private static <T> T addMatcher(ArgumentMatcher argument, T value) {
-    sMatchArguments.add(argument);
-    return value;
-  }
-
-  /** A custom argument matcher, should be used only for object arguments not primitives. */
-  public static <T> T matches(ArgumentMatcher argument) {
-    sMatchArguments.add(argument);
-    return null;
-  }
-
-  /** Utility method to throw an AssertionError if an assertion fails. */
-  private static void expect(boolean result, String message) {
-    if (!result) {
-      fail(message);
-    }
-  }
-
-  /** Throws an AssertionError exception with a message. */
-  private static void fail(String message) {
-    throw new AssertionError(message);
-  }
-
-  /** Static mapping from class type to default value for that type. */
-  private static final Map<Class<?>, Object> DEFAULT_RETURN_VALUE_LOOKUP;
-  static {
-    DEFAULT_RETURN_VALUE_LOOKUP = new HashMap<Class<?>, Object>();
-    DEFAULT_RETURN_VALUE_LOOKUP.put(int.class, 0);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(boolean.class, false);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(byte.class, (byte) 0);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(long.class, (long) 0);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(short.class, (short) 0);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(float.class, (float) 0);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(double.class, (double) 0);
-    DEFAULT_RETURN_VALUE_LOOKUP.put(char.class, '\u0000');
-    DEFAULT_RETURN_VALUE_LOOKUP.put(String.class, null);
-  }
-
-  /** Static lookup from primitive types to their boxed versions. */
-  private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_BOXED_LOOKUP;
-  static {
-    PRIMITIVE_TO_BOXED_LOOKUP = new HashMap<Class<?>, Class<?>>();
-    PRIMITIVE_TO_BOXED_LOOKUP.put(int.class, Integer.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(boolean.class, Boolean.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(byte.class, Byte.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(long.class, Long.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(short.class, Short.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(float.class, Float.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(double.class, Double.class);
-    PRIMITIVE_TO_BOXED_LOOKUP.put(char.class, Character.class);
-  }
-
-  /** For a given class type, returns the default value for that type. */
-  private static Object defaultReturnValue(Class<?> returnType) {
-    return DEFAULT_RETURN_VALUE_LOOKUP.get(returnType);
-  }
-
-  /** Gets a suitable class loader for use with the proxy. */
-  private static ClassLoader getClassLoader() {
-    return LittleMock.class.getClassLoader();
-  }
-
-  /** Sets a member field on an object via reflection (can set private members too). */
-  private static void setField(Field field, Object object, Object value) throws Exception {
-    field.setAccessible(true);
-    field.set(object, value);
-    field.setAccessible(false);
-  }
-
-  /** Helper method to throw an IllegalStateException if given condition is not met. */
-  private static void checkState(boolean condition, String message) {
-    if (!condition) {
-      throw new IllegalStateException(message);
-    }
-  }
-
-  /** Helper method to throw an IllegalStateException if given condition is not met. */
-  private static void checkState(boolean condition) {
-    if (!condition) {
-      throw new IllegalStateException();
-    }
-  }
-
-  /**
-   * If the input object is one of our mocks, returns the {@link DefaultInvocationHandler}
-   * we constructed it with.  Otherwise fails with {@link IllegalArgumentException}.
-   */
-  private static DefaultInvocationHandler getHandlerFrom(Object mock) {
-    try {
-      InvocationHandler invocationHandler = Proxy.getInvocationHandler(mock);
-      if (invocationHandler instanceof DefaultInvocationHandler) {
-        return (DefaultInvocationHandler) invocationHandler;
-      }
-    } catch (IllegalArgumentException expectedIfNotAProxy) {}
-    try {
-      Class<?> proxyBuilder = Class.forName("com.google.dexmaker.stock.ProxyBuilder");
-      Method getHandlerMethod = proxyBuilder.getMethod("getInvocationHandler", Object.class);
-      Object invocationHandler = getHandlerMethod.invoke(proxyBuilder, mock);
-      if (invocationHandler instanceof DefaultInvocationHandler) {
-        return (DefaultInvocationHandler) invocationHandler;
-      }
-    } catch (Exception expectedIfNotAProxyBuilderMock) {}
-    try {
-      // Try with javassist.
-      Class<?> proxyObjectClass = Class.forName("javassist.util.proxy.ProxyObject");
-      Method getHandlerMethod = proxyObjectClass.getMethod("getHandler");
-      Object methodHandler = getHandlerMethod.invoke(mock);
-      InvocationHandler invocationHandler = Proxy.getInvocationHandler(methodHandler);
-      Method getOriginalMethod = invocationHandler.getClass().getMethod("$$getOriginal");
-      Object original = getOriginalMethod.invoke(invocationHandler);
-      if (original instanceof DefaultInvocationHandler) {
-        return (DefaultInvocationHandler) original;
-      }
-    } catch (Exception expectedIfNotJavassistProxy) {}
-    throw new IllegalArgumentException("not a valid mock: " + mock);
-  }
-
-  private static boolean canUseJavassist() {
-      try {
-          Class.forName("javassist.util.proxy.ProxyFactory");
-          return true;
-      } catch (Exception expectedIfNotJavassistProxy) {
-          return false;
-      }
-  }
-
-  /** Create a dynamic proxy for the given class, delegating to the given invocation handler. */
-  private static Object createProxy(Class<?> clazz, final InvocationHandler handler) {
-    // Interfaces are simple.  Just proxy them using java.lang.reflect.Proxy.
-    if (clazz.isInterface()) {
-      return Proxy.newProxyInstance(getClassLoader(), new Class<?>[] { clazz }, handler);
-    }
-    // Try with javassist.
-    if (canUseJavassist()) {
-        try {
-          Class<?> proxyFactoryClass = Class.forName("javassist.util.proxy.ProxyFactory");
-          Object proxyFactory = proxyFactoryClass.newInstance();
-          Method setSuperclassMethod = proxyFactoryClass.getMethod("setSuperclass", Class.class);
-          setSuperclassMethod.invoke(proxyFactory, clazz);
-          Class<?> methodFilterClass = Class.forName("javassist.util.proxy.MethodFilter");
-          InvocationHandler methodFilterHandler = new InvocationHandler() {
-            @Override
-            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-              checkState(method.getName().equals("isHandled"));
-              checkState(args.length == 1);
-              checkState(args[0] instanceof Method);
-              Method invokedMethod = (Method) args[0];
-              String methodName = invokedMethod.getName();
-              Class<?>[] params = invokedMethod.getParameterTypes();
-              if ("equals".equals(methodName) && params.length == 1
-                  && Object.class.equals(params[0])) {
-                return false;
-              }
-              if ("hashCode".equals(methodName) && params.length == 0) {
-                  return false;
-              }
-              if ("toString".equals(methodName) && params.length == 0) {
-                  return false;
-              }
-              if ("finalize".equals(methodName) && params.length == 0) {
-                  return false;
-              }
-              return true;
-            }
-          };
-          Object methodFilter = Proxy.newProxyInstance(getClassLoader(),
-              new Class<?>[] { methodFilterClass }, methodFilterHandler);
-          Method setFilterMethod = proxyFactoryClass.getMethod("setFilter", methodFilterClass);
-          setFilterMethod.invoke(proxyFactory, methodFilter);
-          Method createClassMethod = proxyFactoryClass.getMethod("createClass");
-          Class<?> createdClass = (Class<?>) createClassMethod.invoke(proxyFactory);
-          InvocationHandler methodHandlerHandler = new InvocationHandler() {
-            @SuppressWarnings("unused")
-            public InvocationHandler $$getOriginal() {
-              return handler;
-            }
-            @Override
-            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-              checkState(method.getName().equals("invoke"));
-              checkState(args.length == 4);
-              checkState(args[1] instanceof Method);
-              Method invokedMethod = (Method) args[1];
-              checkState(args[3] instanceof Object[]);
-              return handler.invoke(args[0], invokedMethod, (Object[]) args[3]);
-            }
-          };
-          Class<?> methodHandlerClass = Class.forName("javassist.util.proxy.MethodHandler");
-          Object methodHandler = Proxy.newProxyInstance(getClassLoader(),
-              new Class<?>[] { methodHandlerClass }, methodHandlerHandler);
-          Object proxy = unsafeCreateInstance(createdClass);
-          Class<?> proxyObjectClass = Class.forName("javassist.util.proxy.ProxyObject");
-          Method setHandlerMethod = proxyObjectClass.getMethod("setHandler", methodHandlerClass);
-          setHandlerMethod.invoke(proxy, methodHandler);
-          return proxy;
-        } catch (Exception e) {
-          // Not supported, something went wrong.  Fall through, try android dexmaker.
-          e.printStackTrace(System.err);
-        }
-    }
-    // So, this is a class.  First try using Android's ProxyBuilder from dexmaker.
-    try {
-      Class<?> proxyBuilder = Class.forName("com.google.dexmaker.stock.ProxyBuilder");
-      Method forClassMethod = proxyBuilder.getMethod("forClass", Class.class);
-      Object builder = forClassMethod.invoke(null, clazz);
-      Method dexCacheMethod = builder.getClass().getMethod("dexCache", File.class);
-      File directory = AppDataDirGuesser.getsInstance().guessSuitableDirectoryForGeneratedClasses();
-      builder = dexCacheMethod.invoke(builder, directory);
-      Method buildClassMethod = builder.getClass().getMethod("buildProxyClass");
-      Class<?> resultClass = (Class<?>) buildClassMethod.invoke(builder);
-      Object proxy = unsafeCreateInstance(resultClass);
-      Field handlerField = resultClass.getDeclaredField("$__handler");
-      handlerField.setAccessible(true);
-      handlerField.set(proxy, handler);
-      return proxy;
-    } catch (Exception e) {
-      throw new IllegalStateException("Could not mock this concrete class", e);
-    }
-  }
-
-  /** Attempt to construct an instance of the class using hacky methods to avoid calling super. */
-  @SuppressWarnings("unchecked")
-  private static <T> T unsafeCreateInstance(Class<T> clazz) {
-    // try jvm
-    try {
-      Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
-      Field f = unsafeClass.getDeclaredField("theUnsafe");
-      f.setAccessible(true);
-      final Object unsafe = f.get(null);
-      final Method allocateInstance = unsafeClass.getMethod("allocateInstance", Class.class);
-      return (T) allocateInstance.invoke(unsafe, clazz);
-    } catch (Exception ignored) {}
-    // try dalvikvm, pre-gingerbread
-    try {
-      final Method newInstance = ObjectInputStream.class.getDeclaredMethod(
-          "newInstance", Class.class, Class.class);
-      newInstance.setAccessible(true);
-      return (T) newInstance.invoke(null, clazz, Object.class);
-    } catch (Exception ignored) {}
-    // try dalvikvm, post-gingerbread
-    try {
-      Method getConstructorId = ObjectStreamClass.class.getDeclaredMethod(
-          "getConstructorId", Class.class);
-      getConstructorId.setAccessible(true);
-      final int constructorId = (Integer) getConstructorId.invoke(null, Object.class);
-      final Method newInstance = ObjectStreamClass.class.getDeclaredMethod(
-          "newInstance", Class.class, int.class);
-      newInstance.setAccessible(true);
-      return (T) newInstance.invoke(null, clazz, constructorId);
-    } catch (Exception ignored) {}
-    throw new IllegalStateException("unsafe create instance failed");
-  }
-
-  /** See {@link LittleMock#inOrder(Object[])}. */
-  public interface InOrder {
-      <T> T verify(T mock);
-  }
-
-  /**
-   * Used to verify that invocations happen in a given order.
-   * <p>
-   * Still slight experimental at the moment: you can only verify one method call at a time,
-   * and we ignore the mocks array you pass in as an argument, you may use the returned inorder
-   * to verify all mocks.
-   * <p>
-   * This implementation is simple: the InOrder you get from this call can be used to verify that
-   * a sequence of method calls happened in the order you specify.  Every verify you make with
-   * this InOrder will be compared with every other verify you made, to make sure that all the
-   * original invocations happened in exactly that same order.
-   */
-  public static InOrder inOrder(Object... mocks) {
-    return new InOrder() {
-      private final OrderChecker mChecker = new OrderChecker();
-      @Override
-      public <T> T verify(T mock) {
-        return LittleMock.verify(mock, times(1), mChecker);
-      }
-    };
-  }
-}
diff --git a/src/com/google/testing/littlemock/Mock.java b/src/com/google/testing/littlemock/Mock.java
deleted file mode 100644
index f4667b7..0000000
--- a/src/com/google/testing/littlemock/Mock.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2011 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.testing.littlemock;
-
-import java.lang.annotation.ElementType;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.annotation.Target;
-
-/**
- * Use this to inject a mock into your test class.
- *
- * <p>Just add the correct annotation to your field like this:
- * <pre>
- *     &#64;Mock private MyInterface mMockMyInterface;
- * </pre>
- *
- * <p>You just have to make sure that {@link LittleMock#initMocks(Object)} is called from
- * your setUp() (or from a test base class), and then all your mocks will be automatically
- * constructed for you.
- *
- * @author hugohudson@gmail.com (Hugo Hudson)
- */
-@Target({ ElementType.FIELD })
-@Retention(RetentionPolicy.RUNTIME)
-public @interface Mock {
-}
diff --git a/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java b/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java
deleted file mode 100644
index 191a608..0000000
--- a/tests/com/google/testing/littlemock/AppDataDirGuesserTest.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2011 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.testing.littlemock;
-
-import junit.framework.TestCase;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.Set;
-
-public class AppDataDirGuesserTest extends TestCase {
-  public void testGuessCacheDir_SimpleExample() {
-    guessCacheDirFor("/data/app/a.b.c.apk").shouldGive("/data/data/a.b.c/cache");
-    guessCacheDirFor("/data/app/a.b.c.tests.apk").shouldGive("/data/data/a.b.c.tests/cache");
-  }
-
-  public void testGuessCacheDir_MultipleResultsSeparatedByColon() {
-    guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk")
-        .shouldGive("/data/data/a.b.c/cache", "/data/data/d.e.f/cache");
-  }
-
-  public void testGuessCacheDir_NotWriteableSkipped() {
-    guessCacheDirFor("/data/app/a.b.c.apk:/data/app/d.e.f.apk")
-        .withNonWriteable("/data/data/a.b.c/cache")
-        .shouldGive("/data/data/d.e.f/cache");
-  }
-
-  public void testGuessCacheDir_StripHyphenatedSuffixes() {
-    guessCacheDirFor("/data/app/a.b.c-2.apk").shouldGive("/data/data/a.b.c/cache");
-  }
-
-  public void testGuessCacheDir_LeadingAndTrailingColonsIgnored() {
-    guessCacheDirFor("/data/app/a.b.c.apk:asdf:").shouldGive("/data/data/a.b.c/cache");
-    guessCacheDirFor(":asdf:/data/app/a.b.c.apk").shouldGive("/data/data/a.b.c/cache");
-  }
-
-  public void testGuessCacheDir_InvalidInputsGiveEmptyArray() {
-    guessCacheDirFor("").shouldGive();
-  }
-
-  public void testGuessCacheDir_JarsIgnored() {
-    guessCacheDirFor("/data/app/a.b.c.jar").shouldGive();
-    guessCacheDirFor("/system/framework/android.test.runner.jar").shouldGive();
-  }
-
-  public void testGuessCacheDir_RealWorldExample() {
-    String realPath = "/system/framework/android.test.runner.jar:" +
-        "/data/app/com.google.android.voicesearch.tests-2.apk:" +
-        "/data/app/com.google.android.voicesearch-1.apk";
-    guessCacheDirFor(realPath)
-        .withNonWriteable("/data/data/com.google.android.voicesearch.tests/cache")
-        .shouldGive("/data/data/com.google.android.voicesearch/cache");
-  }
-
-  public void testSplitPathList() {
-    final String[] expected = { "foo", "bar" };
-    assertTrue(Arrays.equals(expected, AppDataDirGuesser.splitPathList("foo:bar")));
-    assertTrue(Arrays.equals(expected,
-              AppDataDirGuesser.splitPathList("dexPath=foo:bar")));
-    assertTrue(Arrays.equals(expected,
-              AppDataDirGuesser.splitPathList("dexPath=foo:bar,bazPath=bar:bar2")));
-  }
-
-  private interface TestCondition {
-    TestCondition withNonWriteable(String... files);
-    void shouldGive(String... files);
-  }
-
-  private TestCondition guessCacheDirFor(final String path) {
-    final Set<String> notWriteable = new HashSet<String>();
-    return new TestCondition() {
-      @Override
-      public void shouldGive(String... files) {
-        AppDataDirGuesser guesser = new AppDataDirGuesser() {
-          @Override
-          public boolean isWriteableDirectory(File file) {
-            return !notWriteable.contains(file.getAbsolutePath());
-          }
-          @Override
-          boolean fileOrDirExists(File file) {
-            return true;
-          }
-        };
-        File[] results = guesser.guessPath(path);
-        assertNotNull("Null results for " + path, results);
-        assertEquals("Bad lengths for " + path, files.length, results.length);
-        for (int i = 0; i < files.length; ++i) {
-          assertEquals("Element " + i, new File(files[i]), results[i]);
-        }
-      }
-
-      @Override
-      public TestCondition withNonWriteable(String... files) {
-        notWriteable.addAll(Arrays.asList(files));
-        return this;
-      }
-    };
-  }
-}
diff --git a/tests/com/google/testing/littlemock/LittleMockTest.java b/tests/com/google/testing/littlemock/LittleMockTest.java
deleted file mode 100644
index e7f9bca..0000000
--- a/tests/com/google/testing/littlemock/LittleMockTest.java
+++ /dev/null
@@ -1,1684 +0,0 @@
-/*
- * Copyright 2011 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.testing.littlemock;
-
-import static com.google.testing.littlemock.LittleMock.anyBoolean;
-import static com.google.testing.littlemock.LittleMock.anyByte;
-import static com.google.testing.littlemock.LittleMock.anyChar;
-import static com.google.testing.littlemock.LittleMock.anyDouble;
-import static com.google.testing.littlemock.LittleMock.anyFloat;
-import static com.google.testing.littlemock.LittleMock.anyInt;
-import static com.google.testing.littlemock.LittleMock.anyLong;
-import static com.google.testing.littlemock.LittleMock.anyObject;
-import static com.google.testing.littlemock.LittleMock.anyShort;
-import static com.google.testing.littlemock.LittleMock.anyString;
-import static com.google.testing.littlemock.LittleMock.anyTimes;
-import static com.google.testing.littlemock.LittleMock.atLeast;
-import static com.google.testing.littlemock.LittleMock.atLeastOnce;
-import static com.google.testing.littlemock.LittleMock.atMost;
-import static com.google.testing.littlemock.LittleMock.between;
-import static com.google.testing.littlemock.LittleMock.checkForProgrammingErrorsDuringTearDown;
-import static com.google.testing.littlemock.LittleMock.doAnswer;
-import static com.google.testing.littlemock.LittleMock.doNothing;
-import static com.google.testing.littlemock.LittleMock.doReturn;
-import static com.google.testing.littlemock.LittleMock.doThrow;
-import static com.google.testing.littlemock.LittleMock.eq;
-import static com.google.testing.littlemock.LittleMock.inOrder;
-import static com.google.testing.littlemock.LittleMock.initMocks;
-import static com.google.testing.littlemock.LittleMock.isA;
-import static com.google.testing.littlemock.LittleMock.matches;
-import static com.google.testing.littlemock.LittleMock.mock;
-import static com.google.testing.littlemock.LittleMock.never;
-import static com.google.testing.littlemock.LittleMock.reset;
-import static com.google.testing.littlemock.LittleMock.timeout;
-import static com.google.testing.littlemock.LittleMock.times;
-import static com.google.testing.littlemock.LittleMock.verify;
-import static com.google.testing.littlemock.LittleMock.verifyNoMoreInteractions;
-import static com.google.testing.littlemock.LittleMock.verifyZeroInteractions;
-
-import com.google.testing.littlemock.LittleMock.ArgumentMatcher;
-import com.google.testing.littlemock.LittleMock.InOrder;
-
-import junit.framework.TestCase;
-
-import java.io.IOException;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Callable;
-import java.util.concurrent.CancellationException;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-
-/**
- * Unit tests for the LittleMock class.
- *
- * @author hugohudson@gmail.com (Hugo Hudson)
- */
-public class LittleMockTest extends TestCase {
-  @Mock private Foo mFoo;
-  @Mock private Bar mBar;
-  @Mock private BarSubtype mBarSubtype;
-  @Captor private ArgumentCaptor<String> mCaptureString;
-  @Captor private ArgumentCaptor<String> mCaptureAnotherString;
-  @Captor private ArgumentCaptor<Integer> mCaptureInteger;
-  @Captor private ArgumentCaptor<Callback> mCaptureCallback;
-  private ExecutorService mExecutorService;
-
-  @Override
-  protected void setUp() throws Exception {
-    super.setUp();
-    LittleMock.initMocks(this);
-    mExecutorService = Executors.newCachedThreadPool();
-  }
-
-  @Override
-    protected void tearDown() throws Exception {
-      mExecutorService.shutdown();
-      super.tearDown();
-    }
-
-  /** Simple interface for testing against. */
-  public interface Callback {
-    public void callMeNow();
-  }
-
-  /** Simple interface for testing against. */
-  public interface Foo {
-    public int anInt();
-    public boolean aBoolean();
-    public byte aByte();
-    public short aShort();
-    public long aLong();
-    public float aFloat();
-    public double aDouble();
-    public char aChar();
-    public String aString();
-    public Object anObject();
-    public Foo anInterface();
-    public void add(String input);
-    public void clear();
-    public String get(int index);
-    public String lookup(String string);
-    public void getResultLater(Callback callback);
-    public String findByInt(int input);
-    public String findByBoolean(boolean input);
-    public String findByByte(byte input);
-    public String findByShort(short input);
-    public String findByLong(long input);
-    public String findByFloat(float input);
-    public String findByDouble(double input);
-    public String findByChar(char input);
-    public void takesObject(Object input);
-    public void takesList(List<String> input);
-    public void takesBar(Bar bar);
-    public void exceptionThrower() throws Exception;
-    public Bar aBar();
-    public BarSubtype aBarSubtype();
-  }
-
-  /** Simple interface for testing against. */
-  public interface Bar {
-    public void doSomething();
-    public String twoStrings(String first, String second);
-    public void mixedArguments(int first, String second);
-    public void getResultLater(Callback callback);
-  }
-
-  /** Subtype of Bar. */
-  public interface BarSubtype extends Bar {
-    public void doSomethingElse();
-  }
-
-  /** Another interface for testing with. */
-  public interface OnClickListener {
-    void onClick(Bar bar);
-  }
-
-  public void testDefaultReturnTypesForNewMocks() {
-    assertEquals(0, mFoo.anInt());
-    assertEquals(false, mFoo.aBoolean());
-    assertEquals(0, mFoo.aByte());
-    assertEquals(0, mFoo.aShort());
-    assertEquals(0L, mFoo.aLong());
-    assertEquals(0.0f, mFoo.aFloat());
-    assertEquals(0.0d, mFoo.aDouble());
-    assertEquals('\u0000', mFoo.aChar());
-    assertEquals(null, mFoo.aString());
-    assertEquals(null, mFoo.anObject());
-    assertEquals(null, mFoo.anInterface());
-  }
-
-  public void testVerify_FailsIfNotDoneOnAProxy() {
-    try {
-      verify("hello").contains("something");
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testVerify_FailsIfNotCreatedByOurMockMethod() {
-    try {
-      verify(createNotARealMock()).add("something");
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testVerify_SuccessfulVerification() {
-    mFoo.add("something");
-    verify(mFoo).add("something");
-  }
-
-  public void testVerify_SuccessfulVerification_NormalOrder() {
-    mFoo.add("something");
-    mFoo.add("something else");
-    verify(mFoo).add("something");
-    verify(mFoo).add("something else");
-  }
-
-  public void testVerify_SuccessfulVerification_ReverseOrder() {
-    mFoo.add("something");
-    mFoo.add("something else");
-    verify(mFoo).add("something else");
-    verify(mFoo).add("something");
-  }
-
-  public void testVerify_MeansOnlyOnceSoShouldFailIfCalledTwice() {
-    mFoo.add("something");
-    mFoo.add("something");
-    try {
-      verify(mFoo).add("something");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_FailedVerification_CalledWithWrongArgument() {
-    mFoo.add("something else");
-    try {
-      verify(mFoo).add("something");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_FailedVerification_WasNeverCalled() {
-    try {
-      verify(mFoo).add("something");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_TimesTwice_Succeeds() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, LittleMock.times(2)).add("jim");
-  }
-
-  public void testVerify_TimesTwice_ButThreeTimesFails() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    try {
-      verify(mFoo, LittleMock.times(2)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_TimesTwice_ButOnceFails() {
-    mFoo.add("jim");
-    try {
-      verify(mFoo, LittleMock.times(2)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_TimesTwice_DifferentStringsFails() {
-    mFoo.add("jim");
-    mFoo.add("bob");
-    try {
-      verify(mFoo, LittleMock.times(2)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_TimesTwice_WorksWithAnyString() {
-    mFoo.add("jim");
-    mFoo.add("bob");
-    verify(mFoo, LittleMock.times(2)).add(anyString());
-  }
-
-  public void testVerify_TimesTwice_FailsIfJustOnceWithAnyString() {
-    mFoo.add("bob");
-    try {
-      verify(mFoo, LittleMock.times(2)).add(anyString());
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_TimesTwice_FailsIfThreeTimesWithAnyString() {
-    mFoo.add("bob");
-    mFoo.add("jim");
-    mFoo.add("james");
-    try {
-      verify(mFoo, LittleMock.times(2)).add(anyString());
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_Never_Succeeds() {
-    verify(mFoo, never()).add("jim");
-    verify(mFoo, never()).anInt();
-  }
-
-  public void testVerify_Never_FailsIfWasCalled() {
-    mFoo.add("jim");
-    try {
-      verify(mFoo, never()).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_Never_PassesIfArgumentsDontMatch() {
-    mFoo.add("bobby");
-    verify(mFoo, never()).add("jim");
-  }
-
-  public void testVerify_AtLeastOnce_SuceedsForOneCall() {
-    mFoo.add("jim");
-    verify(mFoo, atLeastOnce()).add("jim");
-  }
-
-  public void testVerify_AtLeastOnce_SuceedsForThreeCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, atLeastOnce()).add("jim");
-  }
-
-  public void testVerify_AtLeastOnce_FailsForNoCalls() {
-    try {
-      verify(mFoo, atLeastOnce()).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_AtLeastThreeTimes_SuceedsForThreeCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, atLeast(3)).add("jim");
-  }
-
-  public void testVerify_AtLeastThreeTimes_SuceedsForFiveCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, atLeast(3)).add("jim");
-  }
-
-  public void testVerify_AtLeastThreeTimes_FailsForTwoCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    try {
-      verify(mFoo, atLeast(3)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_AtMostThreeTimes_SuceedsForThreeCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, atMost(3)).add("jim");
-  }
-
-  public void testVerify_AtMostThreeTimes_FailsForFiveCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    try {
-      verify(mFoo, atMost(3)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_AtMostThreeTimes_SucceedsForTwoCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, atMost(3)).add("jim");
-  }
-
-  public void testVerify_AtMostThreeTimes_SucceedsForNoCalls() {
-    verify(mFoo, atMost(3)).add("jim");
-  }
-
-  public void testVerify_BetweenTwoAndFour_SucceedsForTwoCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, between(2, 4)).add("jim");
-  }
-
-  public void testVerify_BetweenTwoAndFour_SucceedsForFourCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    verify(mFoo, between(2, 4)).add("jim");
-  }
-
-  public void testVerify_BetweenTwoAndFour_FailsForOneCall() {
-    mFoo.add("jim");
-    try {
-      verify(mFoo, between(2, 4)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerify_BetweenTwoAndFour_FailsForFiveCalls() {
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    mFoo.add("jim");
-    try {
-      verify(mFoo, LittleMock.between(2, 4)).add("jim");
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testDoReturnWhen_SimpleReturn() {
-    doReturn("first").when(mFoo).get(0);
-    assertEquals("first", mFoo.get(0));
-  }
-
-  public void testDoReturnWhen_LastStubCallWins() {
-    doReturn("first").when(mFoo).get(0);
-    doReturn("second").when(mFoo).get(0);
-    assertEquals("second", mFoo.get(0));
-  }
-
-  public void testDoReturnWhen_CorrectStubMethodIsChosen() {
-    doReturn("one").when(mFoo).get(1);
-    doReturn("two").when(mFoo).get(2);
-    assertEquals("one", mFoo.get(1));
-    assertEquals("two", mFoo.get(2));
-  }
-
-  public void testDoReturnWhen_UnstubbedMethodStillReturnsDefault() {
-    doReturn("one").when(mFoo).get(1);
-    assertEquals(null, mFoo.get(2));
-  }
-
-  public void testDoReturnWhen_CalledOnString() {
-    try {
-      doReturn("first").when("hello").contains("something");
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testDoReturnWhen_CalledOnNonMock() {
-    try {
-      doReturn("first").when(createNotARealMock()).get(0);
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testDoReturnWhen_CanAlsoBeVerified() {
-    // Mockito home page suggests that you don't verify stubbed calls.
-    // I agree.  They support it anyway.  So will I.
-    doReturn("one").when(mFoo).get(8);
-    mFoo.get(8);
-    verify(mFoo).get(8);
-  }
-
-  public void testDoReturn_CanPassIntForIntMethod() {
-    doReturn(90).when(mFoo).anInt();
-    assertEquals(90, mFoo.anInt());
-  }
-
-  // Interesting, you have to explicity convert the Integer class back into an int before it
-  // is happy to accept this.
-  public void testDoReturn_CanPassIntegerClassForIntMethod() {
-    doReturn((int) Integer.valueOf(10)).when(mFoo).anInt();
-    assertEquals(10, mFoo.anInt());
-  }
-
-  public void testDoReturn_PrimitiveLong() {
-    doReturn((long) Long.valueOf(10L)).when(mFoo).aLong();
-    assertEquals(10L, mFoo.aLong());
-  }
-
-  public void testDoReturn_PrimitiveTypes() {
-    doReturn(5).when(mFoo).anInt();
-    assertEquals(5, mFoo.anInt());
-    doReturn((short) 5).when(mFoo).aShort();
-    assertEquals(5, mFoo.aShort());
-    doReturn(true).when(mFoo).aBoolean();
-    assertEquals(true, mFoo.aBoolean());
-    doReturn((byte) 3).when(mFoo).aByte();
-    assertEquals(3, mFoo.aByte());
-    doReturn(0.6f).when(mFoo).aFloat();
-    assertEquals(0.6f, mFoo.aFloat());
-    doReturn(0.7).when(mFoo).aDouble();
-    assertEquals(0.7, mFoo.aDouble());
-    doReturn('c').when(mFoo).aChar();
-    assertEquals('c', mFoo.aChar());
-    assertEquals(null, mFoo.anInterface());
-  }
-
-  public void testDoThrow_SimpleException() {
-    doThrow(new RuntimeException()).when(mFoo).aDouble();
-    try {
-      mFoo.aDouble();
-      fail();
-    } catch (RuntimeException expected) {}
-  }
-
-  public void testDoThrow_IfItDoesntMatchItIsntThrown() {
-    doThrow(new RuntimeException()).when(mFoo).aDouble();
-    mFoo.aChar();
-  }
-
-  public void testDoThrow_KeepsThrowingForever() {
-    doThrow(new RuntimeException()).when(mFoo).aDouble();
-    try {
-      mFoo.aDouble();
-      fail();
-    } catch (RuntimeException expected) {}
-    // This second call should also throw a RuntimeException.
-    try {
-      mFoo.aDouble();
-      fail();
-    } catch (RuntimeException expected) {}
-  }
-
-  public void testDoNothing() {
-    doNothing().when(mFoo).add("first");
-    mFoo.add("first");
-  }
-
-  public void testVerifyZeroInteractions_PassesWhenNothingHasHappened() {
-    verifyZeroInteractions(mFoo);
-  }
-
-  public void testVerifyZeroInteractions_FailsIfSomethingHasHappened() {
-    mFoo.aBoolean();
-    try {
-      verifyZeroInteractions(mFoo);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyZeroInteractions_HappyWithMultipleArguments() {
-    verifyZeroInteractions(mFoo, mBar);
-  }
-
-  public void testVerifyZeroInteractions_ShouldFailEvenIfOtherInteractionsWereFirstVerified() {
-    mFoo.add("test");
-    verify(mFoo).add("test");
-    try {
-      verifyZeroInteractions(mFoo);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyEq_Method() {
-    mFoo.add("test");
-    verify(mFoo).add(eq("test"));
-  }
-
-  public void testVerifyEq_MethodWithTwoSameTypeParameters() {
-    mBar.twoStrings("first", "test");
-    verify(mBar).twoStrings(eq("first"), eq("test"));
-  }
-
-  public void testVerifyEq_MethodWithTwoDifferentTypeParameters() {
-    mBar.mixedArguments(8, "test");
-    verify(mBar).mixedArguments(eq(8), eq("test"));
-  }
-
-  public void testVerifyEq_MethodFailsIfNotEqual() {
-    mFoo.add("bob");
-    try {
-      verify(mFoo).add(eq("jim"));
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyEq_MethodFailsIfJustOneIsNotEqual() {
-    mBar.twoStrings("first", "second");
-    try {
-      verify(mBar).twoStrings(eq("first"), eq("third"));
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyEq_MethodFailsIfSameParamsButInWrongOrder() {
-    mBar.twoStrings("first", "second");
-    try {
-      verify(mBar).twoStrings(eq("second"), eq("first"));
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testCapture_SimpleCapture() {
-    // We verify that there are zero matchers by using the check for programming errors method.
-    checkForProgrammingErrorsDuringTearDown();
-    mFoo.add("test");
-    verify(mFoo).add(mCaptureString.capture());
-    assertEquals("test", mCaptureString.getValue());
-    checkForProgrammingErrorsDuringTearDown();
-  }
-
-  public void testCapture_DuringStubbing() {
-    checkForProgrammingErrorsDuringTearDown();
-    doReturn("hello").when(mFoo).lookup(mCaptureString.capture());
-
-    assertEquals("hello", mFoo.lookup("what"));
-    assertEquals("what", mCaptureString.getValue());
-  }
-
-  public void testCapture_TwoCallbacksDuringStubbing() {
-    checkForProgrammingErrorsDuringTearDown();
-    doNothing().when(mFoo).add(mCaptureString.capture());
-    doNothing().when(mFoo).getResultLater(mCaptureCallback.capture());
-
-    mFoo.add("hi");
-    assertEquals("hi", mCaptureString.getValue());
-
-    Callback callback = createNoOpCallback();
-    mFoo.getResultLater(callback);
-    assertEquals(callback, mCaptureCallback.getValue());
-  }
-
-  // TODO(hugohudson): 6. Is this impossible to fix?  You can't pass a
-  // createCapture().capture() into a method expecting an int, because the capture
-  // method returns null, and that gets auto-boxed to Integer on the way out of the
-  // capture method, then auto-unboxed into an int when being passed to the underlying
-  // method, which gives the NPE.  How best can we fix this?
-  // It's not like you need to anyway - there's no point / need to capture a primitive,
-  // just use eq(5) for example.
-  public void testCapture_NPEWhenUnboxing() {
-    try {
-      mBar.mixedArguments(5, "ten");
-      verify(mBar).mixedArguments(mCaptureInteger.capture(), mCaptureString.capture());
-      // These lines are never reached, the previous line throws an NPE.
-      fail("You shouldn't be able to reach here");
-      assertEquals(Integer.valueOf(5), mCaptureInteger.getValue());
-      assertEquals("ten", mCaptureString.getValue());
-    } catch (NullPointerException e) {
-      // Expected, unfortunately.
-      // Now also we're in the situation where we have some captures hanging about in the static
-      // variable, which will cause the tear down of this method to fail - we can clear them
-      // as follows:
-      try {
-        checkForProgrammingErrorsDuringTearDown();
-        fail("Expected an IllegalStateException");
-      } catch (IllegalStateException e2) {
-        // Expected.
-      }
-    }
-  }
-
-  public void testCapture_MultiCapture() {
-    mFoo.lookup("james");
-    mFoo.add("whinny");
-    mFoo.add("jessica");
-    verify(mFoo).lookup(mCaptureString.capture());
-    verify(mFoo, atLeastOnce()).add(mCaptureAnotherString.capture());
-    assertEquals("james", mCaptureString.getValue());
-    assertEquals("jessica", mCaptureAnotherString.getValue());
-    assertEquals(newList("whinny", "jessica"), mCaptureAnotherString.getAllValues());
-  }
-
-  public void testAnyString() {
-    doReturn("jim").when(mFoo).lookup(anyString());
-    assertEquals("jim", mFoo.lookup("barney"));
-  }
-
-  public void testAnyString_ObjectArgument() {
-    // It can also be passed to a method that takes object.
-    mFoo.takesObject("barney");
-    verify(mFoo).takesObject(anyString());
-  }
-
-  public void testAnyString_ObjectValue() {
-    mFoo.takesObject(new Object());
-    try {
-      verify(mFoo).takesObject(anyString());
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testAnyObject() {
-    doReturn("jim").when(mFoo).lookup((String) anyObject());
-    assertEquals("jim", mFoo.lookup("barney"));
-  }
-
-  public void testAnyPrimitives() {
-    mFoo.findByBoolean(true);
-    mFoo.findByInt(10000);
-    mFoo.findByByte((byte) 250);
-    mFoo.findByShort((short) 6666);
-    mFoo.findByLong(13L);
-    mFoo.findByFloat(8f);
-    mFoo.findByDouble(1.1);
-    mFoo.findByChar('h');
-    verify(mFoo).findByBoolean(anyBoolean());
-    verify(mFoo).findByInt(anyInt());
-    verify(mFoo).findByByte(anyByte());
-    verify(mFoo).findByShort(anyShort());
-    verify(mFoo).findByLong(anyLong());
-    verify(mFoo).findByFloat(anyFloat());
-    verify(mFoo).findByDouble(anyDouble());
-    verify(mFoo).findByChar(anyChar());
-  }
-
-  public void testAnyPrimitivesWhenMatching() {
-    doReturn("a").when(mFoo).findByBoolean(anyBoolean());
-    doReturn("b").when(mFoo).findByInt(anyInt());
-    doReturn("c").when(mFoo).findByByte(anyByte());
-    doReturn("d").when(mFoo).findByShort(anyShort());
-    doReturn("e").when(mFoo).findByLong(anyLong());
-    doReturn("f").when(mFoo).findByFloat(anyFloat());
-    doReturn("g").when(mFoo).findByDouble(anyDouble());
-    doReturn("h").when(mFoo).findByChar(anyChar());
-    assertEquals("a", mFoo.findByBoolean(true));
-    assertEquals("b", mFoo.findByInt(388));
-    assertEquals("c", mFoo.findByByte((byte) 38));
-    assertEquals("d", mFoo.findByShort((short) 16));
-    assertEquals("e", mFoo.findByLong(1000000L));
-    assertEquals("f", mFoo.findByFloat(15.3f));
-    assertEquals("g", mFoo.findByDouble(13.3));
-    assertEquals("h", mFoo.findByChar('i'));
-  }
-
-  public void testReset_NoInteractionsAfterReset() {
-    mFoo.aByte();
-    reset(mFoo);
-    verifyZeroInteractions(mFoo);
-  }
-
-  public void testReset_VerifyFailsAfterReset() {
-    mFoo.aByte();
-    reset(mFoo);
-    try {
-      verify(mFoo).aByte();
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testCapture_BothBeforeAndAfter() {
-    doNothing().when(mFoo).add(mCaptureString.capture());
-    mFoo.add("first");
-    verify(mFoo).add(mCaptureAnotherString.capture());
-    assertEquals("first", mCaptureString.getValue());
-    assertEquals("first", mCaptureAnotherString.getValue());
-  }
-
-  public void testDoAction_NormalOperation() {
-    doAnswer(new Callable<Boolean>() {
-      @Override
-      public Boolean call() throws Exception {
-        return Boolean.TRUE;
-      }
-    }).when(mFoo).aBoolean();
-    assertEquals(true, mFoo.aBoolean());
-  }
-
-  public void testComplexSituationWithCallback() {
-    // I want to specify that when hasCallback(Callback) method is called, the framework
-    // should immediately call on the captured callback.
-    doAnswer(new CallCapturedCallbackCallable())
-        .when(mBar).getResultLater(mCaptureCallback.capture());
-
-    // The test.
-    mBar.getResultLater(new Callback() {
-      @Override
-      public void callMeNow() {
-        mFoo.add("yes");
-      }
-    });
-
-    verify(mFoo).add("yes");
-  }
-
-  public void testDoAction_CanThrowDeclaredException() throws Exception {
-    doAnswer(new Callable<Void>() {
-      @Override
-      public Void call() throws Exception {
-        throw new IOException("Problem");
-      }
-    }).when(mFoo).exceptionThrower();
-    try {
-      mFoo.exceptionThrower();
-      fail();
-    } catch (IOException expected) {}
-  }
-
-  public void testDoAction_CanThrowUndelcaredException() {
-    doAnswer(new Callable<Void>() {
-      @Override
-      public Void call() throws Exception {
-        throw new RuntimeException("Problem");
-      }
-    }).when(mFoo).aBoolean();
-    try {
-      mFoo.aBoolean();
-      fail();
-    } catch (RuntimeException expected) {}
-  }
-
-  public void testRunThisIsAnAliasForDoAction() {
-    doAnswer(new Callable<Boolean>() {
-      @Override
-      public Boolean call() throws Exception {
-        return Boolean.TRUE;
-      }
-    }).when(mFoo).aBoolean();
-    assertEquals(true, mFoo.aBoolean());
-  }
-
-  public void testVerifyingTwice() {
-    // Behaviour from Mockito docs online seems to be undefined for what should happen if you
-    // try to verify the same behaviour twice.
-    // I'm going to make a call on this one until I have more concrete information, and my
-    // call is that it is okay to verify the same thing twice - a verify doesn't "consume"
-    // the other verifications.
-    // Thus this will pass:
-    mFoo.aByte();
-    verify(mFoo).aByte();
-    verify(mFoo).aByte();
-  }
-
-  public void testVerifyNoMoreInteractions_SuccessWhenNoInteractions() {
-    // Not absolutely certain how this is supposed to behave.
-    // My guess is that every verify "tags" all the methods it verifies against.
-    // Then verifyNoMoreInteractions() will pass only if there are no "untagged" method calls.
-    // Thus, for a start, no interactions will pass.
-    verifyNoMoreInteractions(mFoo, mBar);
-  }
-
-  public void testVerifyNoMoreInteractions_SuccessWhenOneActionWasVerified() {
-    mFoo.aBoolean();
-    verify(mFoo).aBoolean();
-    verifyNoMoreInteractions(mFoo, mBar);
-  }
-
-  public void testVerifyNoMoreInteractions_FailsWhenOneActionWasNotVerified() {
-    mFoo.aBoolean();
-    try {
-      verifyNoMoreInteractions(mFoo, mBar);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyNoMoreInteractions_SucceedsWhenAllActionsWereVerified() {
-    mFoo.get(3);
-    mFoo.get(20);
-    verify(mFoo, atLeastOnce()).get(anyInt());
-    verifyNoMoreInteractions(mFoo);
-  }
-
-  public void testVerifyNoMoreInteractions_FailsWhenMostButNotAllActionsWereVerified() {
-    mFoo.get(3);
-    mFoo.get(20);
-    mFoo.aByte();
-    verify(mFoo, atLeastOnce()).get(anyInt());
-    try {
-      verifyNoMoreInteractions(mFoo);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyNoMoreInteractions_ShouldIngoreStubbedCalls() {
-    doReturn("hi").when(mFoo).get(8);
-    mFoo.get(8);
-    verifyNoMoreInteractions(mFoo);
-  }
-
-  public void testMatchers_WrongNumberOfMatchersOnStubbingCausesError() {
-    try {
-      doReturn("hi").when(mBar).twoStrings("jim", eq("bob"));
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testMatchers_WrongNumberOfMatchersOnVerifyCausesError() {
-    try {
-      verify(mBar).twoStrings("jim", eq("bob"));
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testCreateACaptureButDontUseItShouldFailAtNextVerify() {
-    // If we create a capture illegally, outside of a method call, like so:
-    mCaptureString.capture();
-    // Then we will have illegally created an extra matcher object that we shouldn't have
-    // created that is now sitting on the stack, and that will confuse the next true method
-    // call on the mock object.
-    // Thus we should check in the verify() method that there are *no matchers* on the static
-    // list, as this would indicate a programming error such as the above.
-    try {
-      verify(mFoo, anyTimes()).aBoolean();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testCreateACaptureButDontUseItShouldFailAtNextVerify_AlsoNoMoreInteractions() {
-    // Same result desired as in previous test.
-    mCaptureString.capture();
-    try {
-      verifyNoMoreInteractions(mFoo);
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testCreateACaptureButDontUseItShouldFailAtNextVerify_AlsoZeroInteraction() {
-    mCaptureString.capture();
-    try {
-      verifyZeroInteractions(mFoo);
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testCheckStaticVariablesMethod() {
-    // To help us avoid programming errors, I'm adding a method that you can call from tear down,
-    // which will explode if there is anything still left in your static variables at the end
-    // of the test (so that you know you did something wrong) and that also clears that static
-    // variable (so that the next test won't fail).  It should fail if we create a matcher
-    // be it a capture or anything else that is then not consumed.
-    anyInt();
-    try {
-      checkForProgrammingErrorsDuringTearDown();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testCantPassNullToVerifyCount() {
-    try {
-      verify(mFoo, null).aBoolean();
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testInjectionInNestedClasses() throws Exception {
-    class Outer {
-      @Mock protected Foo outerMock;
-    }
-    class Inner extends Outer {
-      @Mock protected Foo innerMock;
-    }
-    Inner inner = new Inner();
-    assertNull(inner.innerMock);
-    assertNull(inner.outerMock);
-    initMocks(inner);
-    assertNotNull(inner.innerMock);
-    assertNotNull(inner.outerMock);
-  }
-
-  public void testIsA_Succeeds() {
-    mFoo.takesObject(new Object());
-    verify(mFoo).takesObject(isA(Object.class));
-  }
-
-  public void testIsA_WithSubclass() {
-    mFoo.takesObject("hello");
-    verify(mFoo).takesObject(isA(Object.class));
-    verify(mFoo).takesObject(isA(String.class));
-  }
-
-  public void testIsA_FailsWithSuperclass() {
-    mFoo.takesObject(new Object());
-    try {
-      verify(mFoo).takesObject(isA(String.class));
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testIsA_WillAcceptNull() {
-    mFoo.takesObject(null);
-    verify(mFoo).takesObject(isA(Object.class));
-    verify(mFoo).takesObject(isA(String.class));
-  }
-
-  public void testIsA_MatchSubtype() {
-    mFoo.takesBar(mBarSubtype);
-    verify(mFoo).takesBar(isA(BarSubtype.class));
-  }
-
-  public void testIsA_MatchSubtypeFailed() {
-    mFoo.takesBar(mBar);
-    try {
-      verify(mFoo).takesBar(isA(BarSubtype.class));
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyEquals_ShouldFail() {
-    mFoo.equals(null);
-    try {
-      verify(mFoo).equals(null);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyHashCode_ShouldFail() {
-    mFoo.hashCode();
-    try {
-      verify(mFoo).hashCode();
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testVerifyToString_ShouldFail() {
-    mFoo.toString();
-    try {
-      verify(mFoo).toString();
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testStubEquals_ShouldFail() {
-    try {
-      doReturn(false).when(mFoo).equals(null);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testStubHashCode_ShouldFail() {
-    try {
-      doReturn(0).when(mFoo).hashCode();
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testStubToString_ShouldFail() {
-    try {
-      doReturn("party").when(mFoo).toString();
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testEqualsMethod_DoesntCountAsInteraction() {
-    mFoo.takesBar(mBar);
-    verify(mFoo).takesBar(mBar);
-    verifyNoMoreInteractions(mBar);
-  }
-
-  public void testHashCodeMethod_DoesntCountAsInteraction() {
-    mFoo.hashCode();
-    verifyNoMoreInteractions(mFoo);
-  }
-
-  public void testToStringMethod_DoesntCountAsInteraction() {
-    mFoo.toString();
-    verifyNoMoreInteractions(mFoo);
-  }
-
-  public void testEquals_OnMock() {
-    assertTrue(mFoo.equals(mFoo));
-  }
-
-  public void testHashCode_OnMock() {
-    // The hashCode() is checked against zero, the default int value, to make sure it is actually
-    // being treated differently.
-    // It is possible for a hashCode() to be zero, but very unlikely.
-    assertNotSame(0, mFoo.hashCode());
-  }
-
-  public void testToString_OnMock() {
-    assertTrue(mFoo.toString().contains(Foo.class.getName()));
-  }
-
-  public void testErrorMessages_NoArgMethodAndNoInteractions() {
-    /* I would like the error message to look like this:
-     * Expected exactly 2 calls to:
-     *   mFoo.aBoolean()
-     *   at the.line.where.the.verify.happened:xxx
-     *
-     * No method calls happened to this mock
-     */
-    int verifyLineNumber = 0;
-    try {
-      verifyLineNumber = getNextLineNumber();
-      verify(mFoo, times(2)).aBoolean();
-      fail("Should have thrown an assertion error");
-    } catch (AssertionError e) {
-      // Good, verify that the message is exactly as expected.
-      String expectedMessage =
-          "\nExpected exactly 2 calls to:\n"
-          + "  mFoo.aBoolean()\n"
-          + "  at " + singleLineStackTrace(verifyLineNumber) + "\n"
-          + "\n"
-          + "No method calls happened on this mock\n";
-      assertEquals(expectedMessage, e.getMessage());
-    }
-  }
-
-  public void testErrorMessages_SomeArgsMethodAndSomeInteractions() {
-    /* I would like the error message to look like this:
-     * Expected exactly 1 call to:
-     *   mFoo.add(String)
-     *   at the.line.where.the.verify.happened:xxx
-     *
-     * Method calls that did happen:
-     *   mFoo.aByte()
-     *   at the.line.where.the.byte.happened:xxx
-     *   mFoo.findByBoolean(boolean)
-     *   at the line.where.the.boolean.happened:xxx
-     */
-    int aByteLineNumber = 0;
-    int findByBooleanLineNumber = 0;
-    int verifyLineNumber = 0;
-    try {
-      aByteLineNumber = getNextLineNumber();
-      mFoo.aByte();
-      findByBooleanLineNumber = getNextLineNumber();
-      mFoo.findByBoolean(true);
-      verifyLineNumber = getNextLineNumber();
-      verify(mFoo).add("jim");
-      fail("Should have thrown an assertion error");
-    } catch (AssertionError e) {
-      // Good, verify that the message is exactly as expected.
-      String expectedMessage =
-          "\nExpected exactly 1 call to:\n"
-          + "  mFoo.add(String)\n"
-          + "  at " + singleLineStackTrace(verifyLineNumber) + "\n"
-          + "\n"
-          + "Method calls that did happen:\n"
-          + "  mFoo.aByte()\n"
-          + "  at " + singleLineStackTrace(aByteLineNumber) + "\n"
-          + "  mFoo.findByBoolean(boolean)\n"
-          + "  at " + singleLineStackTrace(findByBooleanLineNumber) + "\n";
-      assertEquals(expectedMessage, e.getMessage());
-    }
-  }
-
-  public void testErrorMessage_DoReturnExplainsWhatWentWrong() {
-    /* I would like the error message to look like this:
-     * Can't return Long from stub for:
-     *   (int) mFoo.anInt()
-     *   at the.line.where.the.assignment.happened:xxx
-     */
-    int lineNumber = 0;
-    try {
-      lineNumber = getNextLineNumber();
-      doReturn(10L).when(mFoo).anInt();
-      fail("Should have thrown an IllegalArgumentException");
-    } catch (IllegalArgumentException e) {
-      // Good, expected, verify the message.
-      String expectedMessage =
-          "\nCan't return Long from stub for:\n"
-          + "  (int) mFoo.anInt()\n"
-          + "  at " + singleLineStackTrace(lineNumber) + "\n";
-      assertEquals(expectedMessage, e.getMessage());
-    }
-  }
-
-  public void testErrorMessage_DoReturnAlsoHasGoodErrorMessageForVoidMethods() {
-    /* I would like the error message to look like this:
-     * Can't return String from stub for:
-     *   (void) mFoo.add(String)
-     *   at the.line.where.the.assignment.happened:xxx
-     */
-    int lineNumber = 0;
-    try {
-      lineNumber = getNextLineNumber();
-      doReturn("hello").when(mFoo).add("jim");
-      fail("Should have thrown an IllegalArgumentException");
-    } catch (IllegalArgumentException e) {
-      // Good, expected, verify the message.
-      String expectedMessage =
-          "\nCan't return String from stub for:\n"
-          + "  (void) mFoo.add(String)\n"
-          + "  at " + singleLineStackTrace(lineNumber) + "\n";
-      assertEquals(expectedMessage, e.getMessage());
-    }
-  }
-
-  public void testDoReturn_ThisShouldFailSinceDoubleIsNotAString() {
-    try {
-      doReturn("hello").when(mFoo).aDouble();
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testDoReturn_ThisShouldPassSinceStringCanBeReturnedFromObjectMethod() {
-    doReturn("hello").when(mFoo).anObject();
-  }
-
-  public void testDoReturn_ThisShouldFailSinceObjectCantBeReturnedFromString() {
-    try {
-      doReturn(new Object()).when(mFoo).aString();
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testDoReturn_ThisShouldFailSinceBarIsNotSubtypeOfBarSubtype() {
-    try {
-      doReturn(mBar).when(mFoo).aBarSubtype();
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testDoReturn_ThisShouldPassSinceBarSubTypeIsABar() {
-    doReturn(mBarSubtype).when(mFoo).aBar();
-  }
-
-  // TODO(hugohudson): 7. Should fix this.
-//  @ShouldThrow(IllegalArgumentException.class)
-  public void testDoReturn_ThisShouldFailBecauseNullIsNotAByte() {
-    doReturn(null).when(mFoo).aByte();
-  }
-
-  // TODO(hugohudson): 7. Should fix this.
-  // Once we fix the previous test we won't need this one.
-  // I'm just demonstrating that currently this fails with NPE at use-time not at stub-time.
-  public void testDoReturn_ThisShouldFailBecauseNullIsNotAByte2() {
-    doReturn(null).when(mFoo).aByte();
-    try {
-      mFoo.aByte();
-      fail();
-    } catch (NullPointerException expected) {}
-  }
-
-  public void testDoReturn_ThisShouldPassSinceNullIsAnObject() {
-    doReturn(null).when(mFoo).anObject();
-  }
-
-  // TODO(hugohudson): 7. Should fix this.
-  // At present we aren't catching this, and would have difficulty doing so since we don't know
-  // the type of the callable.
-//  @ShouldThrow(IllegalArgumentException.class)
-  public void testDoAnswer_ThisShouldFailSinceStringIsNotAByte() {
-    doAnswer(new Callable<String>() {
-      @Override public String call() throws Exception { return "hi"; }
-    }).when(mFoo).aByte();
-  }
-
-  // TODO(hugohudson): 7. Should fix this to give proper message.
-  // We could at least give a good message saying why you get failure - saying that your string
-  // is not a byte, and pointing to where you stubbed it.
-  public void testDoAnswer_ThisShouldFailSinceStringIsNotAByte2() {
-    doAnswer(new Callable<String>() {
-      @Override public String call() throws Exception { return "hi"; }
-    }).when(mFoo).aByte();
-    try {
-      mFoo.aByte();
-      fail();
-    } catch (ClassCastException expected) {}
-  }
-
-  public void testDoAnswer_ShouldHaveSimpleNameOnReturnValue() {
-    try {
-      doReturn("hi").when(mFoo).aBar();
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testCantCreateMockOfNullType() {
-    try {
-      mock(null);
-      fail();
-    } catch (IllegalArgumentException expected) {}
-  }
-
-  public void testCreateMockWithNullFieldName() {
-    OnClickListener mockClickListener = mock(OnClickListener.class);
-    try {
-      verify(mockClickListener).onClick(null);
-      fail();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testDoubleVerifyNoProblems() {
-    // Reusing a mock after a verify should be fine.
-    // There was a bug with this, let's check it doesn't regress.
-    mFoo.aBar();
-    verify(mFoo).aBar();
-
-    mFoo.aByte();
-    verify(mFoo).aByte();
-  }
-
-  public void testUnfinishedVerifyCaughtInTearDown_Issue5() {
-    verify(mFoo);
-    try {
-      checkForProgrammingErrorsDuringTearDown();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testUnfinishedWhenCaughtInTearDown_Issue5() {
-    doThrow(new RuntimeException()).when(mFoo);
-    try {
-      checkForProgrammingErrorsDuringTearDown();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testUnfinishedVerifyCaughtByStartingWhen_Issue5() {
-    verify(mFoo, never());
-    try {
-      doReturn(null).when(mFoo).clear();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testUnfinishedWhenCaughtByStartingVerify_Issue5() {
-    doThrow(new RuntimeException()).when(mFoo);
-    try {
-      verify(mFoo).clear();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testSecondUnfinishedVerifyShouldFailImmediately() throws Exception {
-    verify(mFoo);
-    try {
-      verify(mFoo);
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testSecondUnfinishedWhenShouldFailImmediately() throws Exception {
-    doReturn(null).when(mFoo);
-    try {
-      doReturn(null).when(mFoo);
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testVerifyWithTimeout_SuccessCase() throws Exception {
-    CountDownLatch countDownLatch = new CountDownLatch(1);
-    invokeBarMethodAfterLatchAwait(countDownLatch);
-    doReturn(null).when(mFoo).aBar();
-    verify(mFoo, never()).aBar();
-    countDownLatch.countDown();
-    verify(mFoo, timeout(100)).aBar();
-  }
-
-  public void testVerifyWithTimeout_FailureCase() throws Exception {
-    long start = System.currentTimeMillis();
-    try {
-      verify(mFoo, timeout(10)).aBar();
-      fail();
-    } catch (AssertionError expected) {}
-    long duration = System.currentTimeMillis() - start;
-    assertTrue(duration > 5);
-  }
-
-  public void testVerifyWithTimeoutMultipleInvocations_SuccessCase() throws Exception {
-    CountDownLatch countDownLatch = new CountDownLatch(1);
-    invokeBarMethodAfterLatchAwait(countDownLatch);
-    invokeBarMethodAfterLatchAwait(countDownLatch);
-    doReturn(null).when(mFoo).aBar();
-    verify(mFoo, never()).aBar();
-    countDownLatch.countDown();
-    verify(mFoo, timeout(100).times(2)).aBar();
-    verify(mFoo, timeout(100).atLeast(2)).aBar();
-    verify(mFoo, timeout(100).between(2, 4)).aBar();
-    verify(mFoo, timeout(100).atLeastOnce()).aBar();
-  }
-
-  public void testVerifyWithTimeoutMultipleInvocations_FailureCase() throws Exception {
-    long start = System.currentTimeMillis();
-    mFoo.aBar();
-    try {
-      verify(mFoo, timeout(10).between(2, 3)).aBar();
-      fail();
-    } catch (AssertionError expected) {}
-    long duration = System.currentTimeMillis() - start;
-    assertTrue(duration > 5);
-
-  }
-
-  public void testConcurrentModificationExceptions() throws Exception {
-    // This test concurrently stubs, verifies, and uses a mock.
-    // It used to totally reproducibly throw a ConcurrentModificationException.
-    Future<?> task1 = mExecutorService.submit(new Runnable() {
-      @Override
-      public void run() {
-        while (!Thread.currentThread().isInterrupted()) {
-          mFoo.aBar();
-          Thread.yield();
-        }
-      }
-    });
-    Future<?> task2 = mExecutorService.submit(new Runnable() {
-        @Override
-        public void run() {
-          while (!Thread.currentThread().isInterrupted()) {
-            verify(mFoo, anyTimes()).aBar();
-            Thread.yield();
-          }
-        }
-      });
-    Thread.sleep(20);
-    task1.cancel(true);
-    task2.cancel(true);
-    try {
-      task1.get();
-      fail();
-    } catch (CancellationException expected) {}
-    try {
-      task2.get();
-      fail();
-    } catch (CancellationException expected) {}
-  }
-
-  public void testCannotVerifyFromSecondThreadAfterStubbingInFirst() throws Exception {
-    doReturn(null).when(mFoo).aBar();
-    Future<?> submit = mExecutorService.submit(new Runnable() {
-      @Override
-      public void run() {
-        verify(mFoo, anyTimes()).aBar();
-      }
-    });
-    try {
-      submit.get();
-      fail();
-    } catch (ExecutionException expected) {
-      assertTrue(expected.getCause() instanceof IllegalStateException);
-    }
-  }
-
-  public void testCannotStubFromSecondThreadAfterVerifyingInFirst() throws Exception {
-    mExecutorService.submit(new Runnable() {
-      @Override
-      public void run() {
-        verify(mFoo, anyTimes()).aBar();
-      }
-    }).get();
-    try {
-      doReturn(null).when(mFoo).aBar();
-      fail();
-    } catch (IllegalStateException expected) {}
-  }
-
-  public void testCustomMatcher() {
-    ArgumentMatcher argumentMatcher = new ArgumentMatcher() {
-      @Override
-      public boolean matches(Object value) {
-        return ((String) value).contains("[]");
-      }
-    };
-    mFoo.add("as[]df");
-    mFoo.add("qwer[]asdf");
-    mFoo.add("1234");
-    verify(mFoo, times(3)).add(anyString());
-    verify(mFoo, times(2)).add((String) matches(argumentMatcher));
-  }
-
-  public void testInorderExample_Success() {
-    @SuppressWarnings("unchecked")
-    List<String> firstMock = mock(List.class);
-    @SuppressWarnings("unchecked")
-    List<String> secondMock = mock(List.class);
-    firstMock.add("was called first");
-    secondMock.add("was called second");
-    InOrder inOrder = inOrder(firstMock, secondMock);
-    inOrder.verify(firstMock).add("was called first");
-    inOrder.verify(secondMock).add("was called second");
-  }
-
-  public void testInorderExample_Failure() {
-    @SuppressWarnings("unchecked")
-    List<String> firstMock = mock(List.class);
-    @SuppressWarnings("unchecked")
-    List<String> secondMock = mock(List.class);
-    firstMock.add("was called first");
-    secondMock.add("was called second");
-    InOrder inOrder = inOrder(firstMock, secondMock);
-    inOrder.verify(secondMock).add("was called second");
-    try {
-      inOrder.verify(firstMock).add("was called first");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testInorderInterleave() {
-    @SuppressWarnings("unchecked")
-    List<String> firstMock = mock(List.class);
-    firstMock.add("a");
-    firstMock.add("b");
-    firstMock.add("a");
-
-    // Should be fine to verify a then b, since they happened in that order.
-    InOrder inOrder = inOrder(firstMock);
-    inOrder.verify(firstMock).add("a");
-    inOrder.verify(firstMock).add("b");
-
-    // Should also be fine to inorder verify the other way around, they happened in that order too.
-    inOrder = inOrder(firstMock);
-    inOrder.verify(firstMock).add("b");
-    inOrder.verify(firstMock).add("a");
-
-    // Should be fine to verify "a, b, a" since that too happened.
-    inOrder = inOrder(firstMock);
-    inOrder.verify(firstMock).add("a");
-    inOrder.verify(firstMock).add("b");
-    inOrder.verify(firstMock).add("a");
-
-    // "a, a, b" did not happen.
-    inOrder = inOrder(firstMock);
-    inOrder.verify(firstMock).add("a");
-    inOrder.verify(firstMock).add("a");
-    try {
-      inOrder.verify(firstMock).add("b");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-
-    // "b, a, b" did not happen.
-    inOrder = inOrder(firstMock);
-    inOrder.verify(firstMock).add("b");
-    inOrder.verify(firstMock).add("a");
-    try {
-      inOrder.verify(firstMock).add("b");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-
-    // "b" did not happen twice.
-    inOrder = inOrder(firstMock);
-    inOrder.verify(firstMock).add("b");
-    try {
-      inOrder.verify(firstMock).add("b");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-  }
-
-  public void testInorderComplicatedExample() {
-    // TODO: I'm currently totally ignoring the parameters passed to the inorder method.
-    // I don't understand what the point of them is, anyway.
-    @SuppressWarnings("unchecked")
-    List<String> firstMock = mock(List.class);
-    @SuppressWarnings("unchecked")
-    List<String> secondMock = mock(List.class);
-
-    firstMock.add("1");
-    secondMock.add("2");
-    firstMock.add("3");
-    secondMock.add("4");
-
-    InOrder allInOrder = inOrder(firstMock, secondMock);
-    allInOrder.verify(firstMock).add("1");
-    allInOrder.verify(secondMock).add("2");
-    allInOrder.verify(firstMock).add("3");
-    allInOrder.verify(secondMock).add("4");
-
-    InOrder firstInOrder = inOrder(firstMock, secondMock);
-    firstInOrder.verify(firstMock).add("1");
-    firstInOrder.verify(firstMock).add("3");
-    try {
-      firstInOrder.verify(secondMock).add("2");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-    firstInOrder.verify(secondMock).add("4");
-
-    InOrder secondInOrder = inOrder(firstMock, secondMock);
-    secondInOrder.verify(secondMock).add("2");
-    secondInOrder.verify(secondMock).add("4");
-    try {
-      secondInOrder.verify(firstMock).add("1");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-    try {
-      secondInOrder.verify(firstMock).add("3");
-      throw new IllegalStateException();
-    } catch (AssertionError expected) {}
-  }
-
-  public static class Jim {
-    public int bob() {
-      fail();
-      return 3;
-    }
-  }
-
-  // Does not work on JVM, android only.
-  public void testMockingConcreteClasses() throws Exception {
-    Jim mock = mock(Jim.class);
-    assertEquals(0, mock.bob());
-    doReturn(8).when(mock).bob();
-    assertEquals(8, mock.bob());
-  }
-
-  private Future<Void> invokeBarMethodAfterLatchAwait(final CountDownLatch countDownLatch) {
-    return mExecutorService.submit(new Callable<Void>() {
-      @Override
-      public Void call() throws Exception {
-        countDownLatch.await();
-        mFoo.aBar();
-        return null;
-      }
-    });
-  }
-
-  // TODO(hugohudson): 5. Every method that throws exceptions could be improved by adding
-  // test for the content of the error message.
-
-  // TODO(hugohudson): 5. Make the doReturn() method take variable arguments.
-  // The syntax is:
-  // doReturn(1, 2, 3).when(mFoo).anInt();
-  // And of course means that the method returns 1 the first time, 2, the second and 3 the third.
-  // Note that this doesn't imply verification, and I presume that the 3 is always returned for
-  // the 4th and subsequent times.
-
-  // TODO(hugohudson): 6. Could also offer a nicer syntax for multiple returns like this:
-  // How about doReturn().thenThrow().thenReturn().when(mFoo).aDouble();
-
-  // TODO(hugohudson): 5. Get around to implementing Mockito's when() syntax.
-  // I don't really like it, because it means a lot more static nonsense, with yet more
-  // opportunities to shoot oneself in the foot.
-  // Plus, where's the upside in more than one way to do the same thing - it just gets confusing.
-  // But, I imagine that plenty of people who are familiar with Mockito will want this, so I
-  // probably should do it, plus there's a good argument that it allows typechecking of the
-  // method calls, so I guess we probably should.  Looks like this:
-  // when(mock.foo(0)).thenReturn(1);
-  // when(mock.foo(1)).thenThrow(new RuntimeException)
-  // when(mock.foo(anyInt())).thenReturn("bar")
-  // when(mock.foo(argThat(isValid()))).thenReturn("element")
-  // when(mock.someMethod("some arg")).thenThrow(new RuntimeException()).thenReturn("foo");
-  // when(mock.someMethod("some arg")).thenReturn("one", "two", "three");
-  // when(mock.someMethod(anyString())).thenAnswer(new Answer() {
-  //   @Override
-  //   Object answer(InvocationOnMock invocation) {
-  //     Object[] args = invocation.getArguments();
-  //     Object mock = invocation.getMock();
-  //     return "called with arguments: " + args;
-  //   }
-  // }
-
-  // TODO(hugohudson): 6. Again we can chain things like doNothing() then doThrow() I suppose.
-  // doNothing().doThrow(new RuntimeException()).when(mock).someVoidMethod();
-
-  // TODO(hugohudson): 6. I really like the idea of implementing the Spy, which is a wrapper on
-  // a real object and delegates all calls to that real object, but allows you to intercept
-  // the ones that you want to.
-  // Sounds like it will be particularly good for testing legacy code.
-  // But also wouldn't be so much use without us being able to mock concrete classes, which I
-  // imagine is not on the cards for a while yet.
-
-  // TODO(hugohudson): 6. Could possibly look into more aliases for the common methods, so that
-  // you can do the 'given... when... assertThat...' pattern as follows:
-  //  //given
-  //  given(seller.askForBread()).willReturn(new Bread());
-  //  //when
-  //  Goods goods = shop.buyBread();
-  //  //then
-  //  assertThat(goods, containBread());
-
-  // TODO: All unfinished verify and when statements should have sensible error messages telling
-  // you where the unfinished statement comes from.
-
-  /** Returns the line number of the line following the method call. */
-  private int getNextLineNumber() {
-    return new Exception().getStackTrace()[1].getLineNumber() + 1;
-  }
-
-  /** Returns a string like: "com.google.foo.TestFoo.testMethod(TestFoo:50)" */
-  private String singleLineStackTrace(int lineNumber) {
-    return getClass().getName() + "." + getName() + "(" + getClass().getSimpleName() +
-        ".java:" + lineNumber + ")";
-  }
-
-  /** Simple callable that invokes the callback captured in the callback member variable. */
-  private class CallCapturedCallbackCallable implements Callable<Object> {
-    @Override
-    public Object call() {
-      mCaptureCallback.getValue().callMeNow();
-      return null;
-    }
-  }
-
-  private Foo createNotARealMock() {
-    InvocationHandler handler = new InvocationHandler() {
-      @Override
-      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-        return null;
-      }
-    };
-    Foo notARealMock = (Foo) Proxy.newProxyInstance(
-        getClass().getClassLoader(), new Class<?>[]{ Foo.class }, handler);
-    assertNotNull(notARealMock);
-    return notARealMock;
-  }
-
-  private static Callback createNoOpCallback() {
-    return new Callback() {
-      @Override
-      public void callMeNow() {
-      }
-    };
-  }
-
-  private static <T> List<T> newList(T... things) {
-    ArrayList<T> list = new ArrayList<T>();
-    for (T thing : things) {
-      list.add(thing);
-    }
-    return list;
-  }
-}
