diff --git a/java/src/com/android/inputmethod/latin/ByteArrayWrapper.java b/java/src/com/android/inputmethod/latin/ByteArrayWrapper.java
new file mode 100644
index 0000000000000000000000000000000000000000..15f70c50cc1f58703b6ff3c03fd0e4fa32e41f84
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/ByteArrayWrapper.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface;
+
+/**
+ * This class provides an implementation for the FusionDictionary buffer interface that is backed
+ * by a simpled byte array. It allows to create a binary dictionary in memory.
+ */
+public final class ByteArrayWrapper implements FusionDictionaryBufferInterface {
+    private byte[] mBuffer;
+    private int mPosition;
+
+    public ByteArrayWrapper(final byte[] buffer) {
+        mBuffer = buffer;
+        mPosition = 0;
+    }
+
+    @Override
+    public int readUnsignedByte() {
+        return mBuffer[mPosition++] & 0xFF;
+    }
+
+    @Override
+    public int readUnsignedShort() {
+        final int retval = readUnsignedByte();
+        return (retval << 8) + readUnsignedByte();
+    }
+
+    @Override
+    public int readUnsignedInt24() {
+        final int retval = readUnsignedShort();
+        return (retval << 8) + readUnsignedByte();
+    }
+
+    @Override
+    public int readInt() {
+        final int retval = readUnsignedShort();
+        return (retval << 16) + readUnsignedShort();
+    }
+
+    @Override
+    public int position() {
+        return mPosition;
+    }
+
+    @Override
+    public void position(int position) {
+        mPosition = position;
+    }
+
+    @Override
+    public void put(final byte b) {
+        mBuffer[mPosition++] = b;
+    }
+
+    @Override
+    public int limit() {
+        return mBuffer.length - 1;
+    }
+
+    @Override
+    public int capacity() {
+        return mBuffer.length;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
index 10931555e56e3581a8ad3ceedf3d3a3922efa7ae..5233ed7d380a76563f03306ce707adfa717fa1c4 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictIOUtils.java
@@ -53,64 +53,6 @@ public final class UserHistoryDictIOUtils {
         public int getFrequency(final String word1, final String word2);
     }
 
-    public static final class ByteArrayWrapper implements FusionDictionaryBufferInterface {
-        private byte[] mBuffer;
-        private int mPosition;
-
-        public ByteArrayWrapper(final byte[] buffer) {
-            mBuffer = buffer;
-            mPosition = 0;
-        }
-
-        @Override
-        public int readUnsignedByte() {
-            return mBuffer[mPosition++] & 0xFF;
-        }
-
-        @Override
-        public int readUnsignedShort() {
-            final int retval = readUnsignedByte();
-            return (retval << 8) + readUnsignedByte();
-        }
-
-        @Override
-        public int readUnsignedInt24() {
-            final int retval = readUnsignedShort();
-            return (retval << 8) + readUnsignedByte();
-        }
-
-        @Override
-        public int readInt() {
-            final int retval = readUnsignedShort();
-            return (retval << 16) + readUnsignedShort();
-        }
-
-        @Override
-        public int position() {
-            return mPosition;
-        }
-
-        @Override
-        public void position(int position) {
-            mPosition = position;
-        }
-
-        @Override
-        public void put(final byte b) {
-            mBuffer[mPosition++] = b;
-        }
-
-        @Override
-        public int limit() {
-            return mBuffer.length - 1;
-        }
-
-        @Override
-        public int capacity() {
-            return mBuffer.length;
-        }
-    }
-
     /**
      * Writes dictionary to file.
      */
diff --git a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
index 528028328d3a6141b6075569c9cca154b10dbf00..ab5724724cdb6331774f06d7083e0b8b1dfc86c7 100644
--- a/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserHistoryDictionary.java
@@ -261,7 +261,7 @@ public final class UserHistoryDictionary extends ExpandableDictionary {
             inStream = new FileInputStream(file);
             inStream.read(buffer);
             UserHistoryDictIOUtils.readDictionaryBinary(
-                    new UserHistoryDictIOUtils.ByteArrayWrapper(buffer), listener);
+                    new ByteArrayWrapper(buffer), listener);
         } catch (FileNotFoundException e) {
             // This is an expected condition: we don't have a user history dictionary for this
             // language yet. It will be created sometime later.
diff --git a/tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java
index 211d012d262c9bbb5d8852df831009e9a1bff465..6778e6650a275a6fb4f863a3e9c168a498c445fe 100644
--- a/tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/UserHistoryDictIOUtilsTests.java
@@ -153,7 +153,7 @@ public class UserHistoryDictIOUtilsTests extends AndroidTestCase
             inStream.read(buffer);
 
             UserHistoryDictIOUtils.readDictionaryBinary(
-                    new UserHistoryDictIOUtils.ByteArrayWrapper(buffer), listener);
+                    new ByteArrayWrapper(buffer), listener);
         } catch (FileNotFoundException e) {
             Log.e(TAG, "file not found", e);
         } catch (IOException e) {
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
index b704d08b3a76c6b3b369ec0ace9298b4ef78f147..7890782bf89bfad3df654367fd78e16701ba65f6 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOTests.java
@@ -22,8 +22,8 @@ import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
 import android.util.SparseArray;
 
+import com.android.inputmethod.latin.ByteArrayWrapper;
 import com.android.inputmethod.latin.CollectionUtils;
-import com.android.inputmethod.latin.UserHistoryDictIOUtils;
 import com.android.inputmethod.latin.makedict.BinaryDictInputOutput.FusionDictionaryBufferInterface;
 import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader;
 import com.android.inputmethod.latin.makedict.FusionDictionary.CharGroup;
@@ -106,7 +106,7 @@ public class BinaryDictIOTests extends AndroidTestCase {
             if (bufferType == USE_BYTE_ARRAY) {
                 final byte[] array = new byte[(int)file.length()];
                 inStream.read(array);
-                return new UserHistoryDictIOUtils.ByteArrayWrapper(array);
+                return new ByteArrayWrapper(array);
             } else if (bufferType == USE_BYTE_BUFFER){
                 final ByteBuffer buffer = inStream.getChannel().map(
                         FileChannel.MapMode.READ_ONLY, 0, file.length());
diff --git a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
index 47885f02388245d38064cf6ffa4d68f47e280db6..08ae89b293c5fe6f0df54986e11f16dedc0c8d36 100644
--- a/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
+++ b/tests/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtilsTests.java
@@ -40,7 +40,7 @@ import java.util.HashMap;
 import java.util.Random;
 
 @LargeTest
-public class BinaryDictIOUtilsTests  extends AndroidTestCase {
+public class BinaryDictIOUtilsTests extends AndroidTestCase {
     private static final String TAG = BinaryDictIOUtilsTests.class.getSimpleName();
     private static final FormatSpec.FormatOptions FORMAT_OPTIONS =
             new FormatSpec.FormatOptions(3, true);
@@ -53,12 +53,17 @@ public class BinaryDictIOUtilsTests  extends AndroidTestCase {
         "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
         "\u00FC" /* ü */, "\u00E2" /* â */, "\u00F1" /* ñ */, // accented characters
         "\u4E9C" /* 亜 */, "\u4F0A" /* 伊 */, "\u5B87" /* 宇 */, // kanji
-        "\uD841\uDE28" /* 𠘨 */, "\uD840\uDC0B" /* 𠀋 */, "\uD861\uDeD7" /* 𨛗 */ // surrogate pair
+        "\uD841\uDE28" /* 𠘨 */, "\uD840\uDC0B" /* 𠀋 */, "\uD861\uDED7" /* 𨛗 */ // surrogate pair
     };
 
     public BinaryDictIOUtilsTests() {
+        this(System.currentTimeMillis());
+    }
+
+    public BinaryDictIOUtilsTests(final long seed) {
         super();
-        final Random random = new Random(123456);
+        Log.d(TAG, "Seed for test is " + seed);
+        final Random random = new Random(seed);
         sWords.clear();
         for (int i = 0; i < MAX_UNIGRAMS; ++i) {
             sWords.add(generateWord(random.nextInt()));
diff --git a/tools/dicttool/Android.mk b/tools/dicttool/Android.mk
index d3bff868867e23e77b4996b267d01d4ba7dd596a..c99ba2f990559a4741341589809067a973f3dec5 100644
--- a/tools/dicttool/Android.mk
+++ b/tools/dicttool/Android.mk
@@ -16,10 +16,22 @@
 LOCAL_PATH := $(call my-dir)
 include $(CLEAR_VARS)
 
-LATINIME_BASE_SOURCE_DIRECTORY := ../../java/src/com/android/inputmethod
+BUILD_TOP := ../../../../..
+FRAMEWORK_TOP := $(BUILD_TOP)/frameworks/base/core/java
+LATINIME_DIR := $(BUILD_TOP)/packages/inputmethods/LatinIME
+LATINIME_BASE_SOURCE_DIRECTORY := $(LATINIME_DIR)/java/src/com/android/inputmethod
 LATINIME_CORE_SOURCE_DIRECTORY := $(LATINIME_BASE_SOURCE_DIRECTORY)/latin
 LATINIME_ANNOTATIONS_SOURCE_DIRECTORY := $(LATINIME_BASE_SOURCE_DIRECTORY)/annotations
 MAKEDICT_CORE_SOURCE_DIRECTORY := $(LATINIME_CORE_SOURCE_DIRECTORY)/makedict
+DICTTOOL_COMPAT_TESTS_DIRECTORY := compat
+DICTTOOL_ONDEVICE_TESTS_DIRECTORY := \
+        $(LATINIME_DIR)/tests/src/com/android/inputmethod/latin/makedict/
+
+USED_TARGETTED_UTILS := \
+        $(FRAMEWORK_TOP)/android/util/SparseArray.java \
+        $(FRAMEWORK_TOP)/com/android/internal/util/ArrayUtils.java \
+        $(LATINIME_CORE_SOURCE_DIRECTORY)/CollectionUtils.java \
+        $(LATINIME_CORE_SOURCE_DIRECTORY)/ByteArrayWrapper.java
 
 LOCAL_MAIN_SRC_FILES := $(call all-java-files-under, $(MAKEDICT_CORE_SOURCE_DIRECTORY))
 LOCAL_TOOL_SRC_FILES := $(call all-java-files-under, src)
@@ -29,7 +41,10 @@ LOCAL_SRC_FILES := $(LOCAL_TOOL_SRC_FILES) \
         $(filter-out $(addprefix %/, $(notdir $(LOCAL_TOOL_SRC_FILES))), $(LOCAL_MAIN_SRC_FILES)) \
         $(LOCAL_ANNOTATIONS_SRC_FILES) \
         $(LATINIME_CORE_SOURCE_DIRECTORY)/Constants.java \
-        $(call all-java-files-under, tests)
+        $(call all-java-files-under, tests) \
+        $(call all-java-files-under, $(DICTTOOL_ONDEVICE_TESTS_DIRECTORY)) \
+        $(call all-java-files-under, $(DICTTOOL_COMPAT_TESTS_DIRECTORY)) \
+        $(USED_TARGETTED_UTILS)
 
 LOCAL_JAVA_LIBRARIES := junit
 
diff --git a/tools/dicttool/compat/android/test/AndroidTestCase.java b/tools/dicttool/compat/android/test/AndroidTestCase.java
new file mode 100644
index 0000000000000000000000000000000000000000..d01b7ad7c004c1c02e8d0b35ebdb87f72ff6c727
--- /dev/null
+++ b/tools/dicttool/compat/android/test/AndroidTestCase.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+
+/**
+ * This is a compatibility class that aims at emulating android.test.AndroidTestcase from the
+ * Android library as simply as possible, and only to the extent that is used by the client classes.
+ * Its purpose is to provide compatibility without having to pull the whole Android library.
+ */
+public class AndroidTestCase extends TestCase {
+    public File getCacheDir() {
+        return new File(".");
+    }
+    public AndroidTestCase getContext() {
+        return this;
+    }
+}
diff --git a/tools/dicttool/compat/android/test/MoreAsserts.java b/tools/dicttool/compat/android/test/MoreAsserts.java
new file mode 100644
index 0000000000000000000000000000000000000000..f56420b9c02b67a513ff6a32ce2e82dfdfdcc1e0
--- /dev/null
+++ b/tools/dicttool/compat/android/test/MoreAsserts.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test;
+
+import junit.framework.Assert;
+
+/**
+ * This is a compatibility class that aims at emulating android.test.MoreAsserts from the
+ * Android library as simply as possible, and only to the extent that is used by the client classes.
+ * Its purpose is to provide compatibility without having to pull the whole Android library.
+ */
+public class MoreAsserts {
+    public static void assertNotEqual(Object unexpected, Object actual) {
+        if (equal(unexpected, actual)) {
+            Assert.fail("expected not to be:<" + unexpected + ">");
+        }
+    }
+    private static boolean equal(Object a, Object b) {
+        return a == b || (a != null && a.equals(b));
+    }
+}
diff --git a/tools/dicttool/compat/android/test/suitebuilder/annotation/LargeTest.java b/tools/dicttool/compat/android/test/suitebuilder/annotation/LargeTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed00f8d5f07175d27d43a85aede1ef79468610f8
--- /dev/null
+++ b/tools/dicttool/compat/android/test/suitebuilder/annotation/LargeTest.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.test.suitebuilder.annotation;
+
+/**
+ * This is a compatibility class that aims at emulating the LargeTest annotation from the
+ * Android library as simply as possible, and only to the extent that is used by the client classes.
+ * Its purpose is to provide compatibility without having to pull the whole Android library.
+ */
+public @interface LargeTest {
+}
diff --git a/tools/dicttool/compat/android/util/Log.java b/tools/dicttool/compat/android/util/Log.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9df3a4ae33015003aacf2345e06474a087722d5
--- /dev/null
+++ b/tools/dicttool/compat/android/util/Log.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+/**
+ * This is a compatibility class that aims at emulating android.util.Log from the
+ * Android library as simply as possible, and only to the extent that is used by the client classes.
+ * Its purpose is to provide compatibility without having to pull the whole Android library.
+ */
+public class Log {
+    public static void d(final String tag, final String message) {
+        System.out.println(tag + " : " + message);
+    }
+    public static void d(final String tag, final String message, final Exception e) {
+        System.out.println(tag + " : " + message + " : " + e);
+    }
+    public static void e(final String tag, final String message) {
+        d(tag, message);
+    }
+    public static void e(final String tag, final String message, final Exception e) {
+        e(tag, message, e);
+    }
+}
diff --git a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java
index fdc53b30e20dad6115578dc22411a7f8c1c5cb71..827c5e3a904c7dbf35c9bd99453ccc56ab42bb46 100644
--- a/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java
+++ b/tools/dicttool/src/com/android/inputmethod/latin/dicttool/Test.java
@@ -16,10 +16,16 @@
 
 package com.android.inputmethod.latin.dicttool;
 
+import com.android.inputmethod.latin.makedict.BinaryDictIOUtilsTests;
+import com.android.inputmethod.latin.makedict.BinaryDictInputOutputTest;
+import com.android.inputmethod.latin.makedict.FusionDictionaryTest;
 import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
 
 import java.io.IOException;
 
+/**
+ * Dicttool command implementing self-tests.
+ */
 public class Test extends Dicttool.Command {
     public static final String COMMAND = "test";
 
@@ -37,7 +43,9 @@ public class Test extends Dicttool.Command {
     }
 
     private void test() throws IOException, UnsupportedFormatException {
-        final BinaryDictOffdeviceUtilsTests tests = new BinaryDictOffdeviceUtilsTests();
-        tests.testGetRawDictWorks();
+        new BinaryDictOffdeviceUtilsTests().testGetRawDictWorks();
+        new FusionDictionaryTest().testFusion();
+        new BinaryDictInputOutputTest().testFlattenNodes();
+        new BinaryDictIOUtilsTests().testRandomWords();
     }
 }
diff --git a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
index fe3781d8079b48d7fb74f3511def8d06dceecb99..76071133d146521b5a1009aa959368f2f1b2adec 100644
--- a/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
+++ b/tools/dicttool/tests/com/android/inputmethod/latin/makedict/FusionDictionaryTest.java
@@ -73,10 +73,6 @@ public class FusionDictionaryTest extends TestCase {
         for (final String word : words) {
             if (--limit < 0) return;
             final CharGroup cg = FusionDictionary.findWordInTree(dict.mRoot, word);
-            if (null == cg) {
-                System.out.println("word " + dumpWord(word));
-                dumpDict(dict);
-            }
             assertNotNull(cg);
         }
     }