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()); + } }