diff --git a/resources/sql/autopatches/20140223.bigutf8scratch.sql b/resources/sql/autopatches/20140223.bigutf8scratch.sql
new file mode 100644
index 0000000000..43bd1891ce
--- /dev/null
+++ b/resources/sql/autopatches/20140223.bigutf8scratch.sql
@@ -0,0 +1,2 @@
+ALTER TABLE {$NAMESPACE}_harbormaster.harbormaster_scratchtable
+  ADD bigData LONGTEXT COLLATE utf8_bin;
diff --git a/src/applications/harbormaster/storage/HarbormasterScratchTable.php b/src/applications/harbormaster/storage/HarbormasterScratchTable.php
index ad58120c85..518bdcdc5f 100644
--- a/src/applications/harbormaster/storage/HarbormasterScratchTable.php
+++ b/src/applications/harbormaster/storage/HarbormasterScratchTable.php
@@ -1,13 +1,14 @@
 <?php
 
 /**
  * This is just a test table that unit tests can use if they need to test
  * generic database operations. It won't change and break tests and stuff, and
  * mistakes in test construction or isolation won't impact the application in
  * any way.
  */
 final class HarbormasterScratchTable extends HarbormasterDAO {
 
   protected $data;
+  protected $bigData;
 
 }
diff --git a/src/infrastructure/__tests__/PhabricatorInfrastructureTestCase.php b/src/infrastructure/__tests__/PhabricatorInfrastructureTestCase.php
index 70ba05bb4b..7697f344b1 100644
--- a/src/infrastructure/__tests__/PhabricatorInfrastructureTestCase.php
+++ b/src/infrastructure/__tests__/PhabricatorInfrastructureTestCase.php
@@ -1,27 +1,81 @@
 <?php
 
 final class PhabricatorInfrastructureTestCase
   extends PhabricatorTestCase {
 
+  protected function getPhabricatorTestCaseConfiguration() {
+    return array(
+      self::PHABRICATOR_TESTCONFIG_BUILD_STORAGE_FIXTURES => true,
+    );
+  }
+
   /**
    * This is more of an acceptance test case instead of a unittest. It verifies
    * that all symbols can be loaded correctly. It can catch problems like
    * missing methods in descendants of abstract base classes.
    */
   public function testEverythingImplemented() {
     id(new PhutilSymbolLoader())->selectAndLoadSymbols();
   }
 
   public function testApplicationsInstalled() {
     $all = PhabricatorApplication::getAllApplications();
     $installed = PhabricatorApplication::getAllInstalledApplications();
 
     $this->assertEqual(
       count($all),
       count($installed),
       'In test cases, all applications should default to installed.');
   }
 
+  public function testMySQLAgreesWithUsAboutBMP() {
+    // Build a string with every BMP character in it, then insert it into MySQL
+    // and read it back. We expect to get the same string out that we put in,
+    // demonstrating that strings which pass our BMP checks are also valid in
+    // MySQL and no silent data truncation will occur.
+
+    $buf = '';
+
+    for ($ii = 0x01; $ii <= 0x7F; $ii++) {
+      $buf .= chr($ii);
+    }
+
+    for ($ii = 0xC2; $ii <= 0xDF; $ii++) {
+      for ($jj = 0x80; $jj <= 0xBF; $jj++) {
+        $buf .= chr($ii).chr($jj);
+      }
+    }
+
+    // NOTE: This is \xE0\xA0\xZZ.
+    for ($ii = 0xE0; $ii <= 0xE0; $ii++) {
+      for ($jj = 0xA0; $jj <= 0xBF; $jj++) {
+        for ($kk = 0x80; $kk <= 0xBF; $kk++) {
+          $buf .= chr($ii).chr($jj).chr($kk);
+        }
+      }
+    }
+
+    // NOTE: This is \xE1\xZZ\xZZ through \xEF\xZZ\xZZ.
+    for ($ii = 0xE1; $ii <= 0xEF; $ii++) {
+      for ($jj = 0x80; $jj <= 0xBF; $jj++) {
+        for ($kk = 0x80; $kk <= 0xBF; $kk++) {
+          $buf .= chr($ii).chr($jj).chr($kk);
+        }
+      }
+    }
+
+    $this->assertEqual(194431, strlen($buf));
+    $this->assertEqual(true, phutil_is_utf8_with_only_bmp_characters($buf));
+
+    $write = id(new HarbormasterScratchTable())
+      ->setData('all.utf8.bmp')
+      ->setBigData($buf)
+      ->save();
+
+    $read = id(new HarbormasterScratchTable())->load($write->getID());
+
+    $this->assertEqual($buf, $read->getBigData());
+  }
 
 }