diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml new file mode 100644 index 0000000..0e0c96c --- /dev/null +++ b/.github/workflows/build-and-test.yml @@ -0,0 +1,54 @@ +name: Continuous Integration +on: + pull_request: +jobs: + build: + name: HHVM ${{matrix.hhvm}} - ${{matrix.os}} + strategy: + # Run tests on all OS's and HHVM versions, even if one fails + fail-fast: false + matrix: + os: [ ubuntu ] + hhvm: + - '4.80' + runs-on: ${{matrix.os}}-latest + steps: + - uses: actions/checkout@v2 + - name: Install Composer + run: .github/workflows/install-composer.sh --install-dir=${{runner.temp}} + - name: Install HHVM (apt) + if: matrix.os == 'ubuntu' + run: | + set -ex + export DEBIAN_FRONTEND=noninteractive + sudo apt-get update + sudo apt-get install -y software-properties-common apt-transport-https + sudo apt-key add .github/workflows/hhvm.gpg.key + if [ "${{matrix.hhvm}}" = "nightly" ]; then + sudo add-apt-repository https://dl.hhvm.com/ubuntu + sudo apt-get install -y hhvm-nightly + elif [ "${{matrix.hhvm}}" = "latest" ]; then + sudo add-apt-repository https://dl.hhvm.com/ubuntu + sudo apt-get install -y hhvm + else + DISTRO=$(lsb_release --codename --short) + sudo add-apt-repository \ + "deb https://dl.hhvm.com/ubuntu ${DISTRO}-${{matrix.hhvm}} main" + sudo apt remove hhvm + sudo apt-get install -y hhvm + fi + - name: Inspect HHVM and Hack versions + run: | + hhvm --version + hh_client --version + - name: Create branch for version alias + run: git checkout -b CI_current_pull_request + - name: Install project dependencies + run: php ${{runner.temp}}/composer.phar install + - name: Typecheck + run: hh_client + - name: Run tests + run: vendor/bin/hacktest tests/ + - name: Run lint + if: matrix.hhvm != 'nightly' + run: vendor/bin/hhast-lint diff --git a/.github/workflows/hhvm.gpg.key b/.github/workflows/hhvm.gpg.key new file mode 100644 index 0000000..cd32c2f --- /dev/null +++ b/.github/workflows/hhvm.gpg.key @@ -0,0 +1,36 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v1 + +mQINBFn8koEBEAC2tPtkphj8gZYHI9mTNUHfQalDo+MNWTGUTNB42asjhTNjipzM +VSxjaZSl5cMLg5YCRuT0AbSIe529FH23yEElc03cGVGgoEnmXtE4+2v7Xa30wCGO +5oUxKfbVatsxEs1y8QEr5Gt+CUFmsApOKgiZq0MsPYmFAuC9CbWdXYa8+E00bXOa +cHCpe+GncCxQmExm7TlrUnURnf3RnNWSEkuPKED/aVggzxNVN6RgRRm4ssZJasM3 +TwoI1nVysO5jMfPClvupYscoktO44HBZzH2EeEdpjSV+toD3aZCbmWzXyZjogrFN +j4k5Mme0Xqr4DvRPk5M9SxcQASsCQ8VTyu+ZBUG6zJbddLDEA1BMNIZOG5MyX58O +zed255Q85SAyjHu8pltkfGLd56+MYsckpHaBPMFoCFM4iPcpXOlgcU96pdXJbrR2 +mjYI4Le9qRJYYP2kGPkopPwK8nbZJ5Wr7xaclxEc/ODH3mv57KJD7lzmwpnvvmsn +kR/wUHOqwrXojp/oZCUK8KembLiT+MMkY3bne+IY9ef/1qwu4flVBP1CpoaMQEwh +dqzihfwyQ+57ATZHJaj8V9pKAxWh/Df4iFN5mMWA15eBLhRMbAWKJIoLQLcCYwBF +gH3HiO34/uQUHaX6VhRHllA38WUoZNhKmw/Kcd/FDQWlbzbgmI89LJEJuwARAQAB +tC1ISFZNIFBhY2thZ2UgU2lnbmluZyA8b3BlbnNvdXJjZStoaHZtQGZiLmNvbT6J +Ak4EEwEIADgWIQQFg0HGj8jeYBfXdaG0ESWF04brlAUCWfySgQIbAwULCQgHAgYV +CAkKCwIEFgIDAQIeAQIXgAAKCRC0ESWF04brlMp8D/4ia7wLi6OQEtR8uPIrtCdg +ClHvXTX0zihHPDomn77lRSfqEVapKcsvpyc9YTjv27EuRvymUG+o7971RY+rYes4 ++POdsjlxJF5ZkNi8YxpUNEw2hTWC66o6vd4Gv4dJgugkZ5dvHKEwec7+mQna9O/p +F4rY/VVmh+4YJUzuuKMb2ZLHsZ3LJv/WBL9Ps+sRFHUN5lDfV00wAsfzEW+dxyh1 +kkqXwTk70r8m5m+nCdf0z+giAU7XWRkbJV2HTatSgY1ozOYARe4v0MGyLwp74I6R +lrWPY97C9k4emF7WP2mglcBu+Eg2Q6A0Y3OgEiGnqkgRJEnrfpHa4wXM1sEUf4MV +5FQgyroZg45c375okr/RLP/pC4/x8ZM6GqLv4qTEOk6qWM7hWXhPRJ1TSVgCHv19 +jki5AkwV4EcROpFmJzfW6V9i4swJKJvYXLr58W0vogsUc8zqII4Sl7JUKZ/oN4jQ +QX138r85fLawla/R0i30njmY7fJYKRwHeshgwHg6vqKobTiPuLarwn0Arv7G7ILP +RjbH/8Pi+U2l8Fm/SjHMZA6gcJteRHjTgjkxSAZ19MyA08YqahJafRUVDY9QhUJb +FkHhptZRf9qRji3+Njhog6s8EGACJSEOwmngAViFVz+UUyOXY94yoHvb19meNecj +ArL3604gOqX3TSSWD1Dcu4kBMwQTAQgAHRYhBDau9k0CB+fu41LUh1oW5ygb56RJ +BQJZ/JVnAAoJEFoW5ygb56RJ15oH/0g4hrylc79TD9xA1vEUexyOdWniY4lwH9yI +/DaFznIMsE1uxmZ0FE9VX5Ks8IFR+3P9mNDQVf9xlVhnR7N597aKtU5GrpbvtlJy +CoQVtzBqYKcuLC4ZFRiB33HwZrZIxTPH27UUaj1QBz748zIMC6wvtldshjNAAeRr +Jz28twPO2D7svNIaPt2+OXAuRs2yUhitcsDLBV0UlOQ8xH+hzWANyhaJAS7p0k35 +kyFOG+n6+2qQkGdlHHuqEzdCL3EiOiK6RrvbWNUnwiG3BdZWgs43hZZBAseX3CHu +MM3vIX/Fc/kuuaCWi2ysyKf7jyi/RiVIAKuLbxAB8eHsyo2G5lA= +=3DTP +-----END PGP PUBLIC KEY BLOCK----- diff --git a/.github/workflows/install-composer.sh b/.github/workflows/install-composer.sh new file mode 100755 index 0000000..94d1d81 --- /dev/null +++ b/.github/workflows/install-composer.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +# From https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md + +EXPECTED_CHECKSUM="$(wget -q -O - https://composer.github.io/installer.sig)" +php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" +ACTUAL_CHECKSUM="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" + +if [ "$EXPECTED_CHECKSUM" != "$ACTUAL_CHECKSUM" ] +then + >&2 echo 'ERROR: Invalid installer checksum' + rm composer-setup.php + exit 1 +fi + +php composer-setup.php "$@" +RESULT=$? +rm composer-setup.php +exit $RESULT diff --git a/.travis.sh b/.travis.sh deleted file mode 100755 index 7ac763e..0000000 --- a/.travis.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh -set -ex -apt update -y -DEBIAN_FRONTEND=noninteractive apt install -y php-cli zip unzip -hhvm --version -php --version - -( - cd $(mktemp -d) - curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer -) -if (hhvm --version | grep -q -- -dev); then - rm -f composer.lock -fi -composer install - -hh_client - -vendor/bin/hacktest tests/ - -vendor/bin/hhast-lint diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0e12cec..0000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -sudo: required -language: generic -services: docker -env: - - HHVM_VERSION=4.41-latest - - HHVM_VERSION=4.56-latest - #- HHVM_VERSION=4.64-latest - #- HHVM_VERSION=latest - # - HHVM_VERSION=nightly hhast needs a newer schema, fails with this nightly - # HipHop VM 4.65.0-dev (rel) - # Compiler: 1593575948_409517482 - # Repo schema: d1ae8e21bf3419a65f12a010527485564e719d07 - - -install: -- docker pull hhvm/hhvm:$HHVM_VERSION -script: -- docker run --rm -w /var/source -v $(pwd):/var/source hhvm/hhvm:$HHVM_VERSION ./.travis.sh diff --git a/composer.json b/composer.json index f3a073e..42ea0bb 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "hhvm/hhvm-autoload": "^2.0.4|^3" }, "require-dev": { - "hhvm/hhast": "^4.0.5", + "hhvm/hhast": "^4.80", "facebook/fbexpect": "^2.2.0", "hhvm/hacktest": "^1.3|^2.0" } diff --git a/maintainers_guide.md b/maintainers_guide.md index 35d4665..f096ee9 100644 --- a/maintainers_guide.md +++ b/maintainers_guide.md @@ -6,6 +6,17 @@ this project. If you use this package within your own software as is but don't p ## Tasks +### Setup + +Install [Composer](https://getcomposer.org/) and PHP. Use PHP to run composer and install dependencies in this working copy. This will create and populate the `vendor/` directory. Note that composer cannot be run with HHVM. + +``` +# if composer installed locally +/usr/bin/php composer.phar install +# if installed globally +/usr/bin/php /usr/local/bin/composer install +``` + ### Testing Run unit tests locally using `vendor/bin/hacktest tests/`. Tests are also run automatically on all branches using [Travis CI](https://travis-ci.org/slackhq/hack-sql-fake). diff --git a/src/AsyncMysql/AsyncMysqlClient.php b/src/AsyncMysql/AsyncMysqlClient.php index 2a0348c..4de8027 100644 --- a/src/AsyncMysql/AsyncMysqlClient.php +++ b/src/AsyncMysql/AsyncMysqlClient.php @@ -24,6 +24,7 @@ public static function setPoolsConnectionLimit(int $_limit): void {} string $_password, int $_timeout_micros = -1, ?\MySSLContextProvider $_ssl_provider = null, + int $_tcp_timeout_micros = 0, ): Awaitable<\AsyncMysqlConnection> { return new AsyncMysqlConnection($host, $port, $dbname); } diff --git a/src/AsyncMysql/AsyncMysqlConnectionPool.php b/src/AsyncMysql/AsyncMysqlConnectionPool.php index f6c22ef..4e79079 100644 --- a/src/AsyncMysql/AsyncMysqlConnectionPool.php +++ b/src/AsyncMysql/AsyncMysqlConnectionPool.php @@ -31,6 +31,7 @@ public function reset(): void { string $_password, int $_timeout_micros = -1, string $_caller = '', + int $_tcp_timeout_micros = 0, ): Awaitable { $this->connectionsRequest++; if (C\contains_key(static::$pool, $host)) { diff --git a/src/BuildSchemaCLI.php b/src/BuildSchemaCLI.php index 51b54f4..cfa5527 100644 --- a/src/BuildSchemaCLI.php +++ b/src/BuildSchemaCLI.php @@ -27,7 +27,7 @@ protected function getSupportedOptions(): vec { if (C\is_empty($this->getArguments())) { $program = $this->getArgv()[0]; - await $terminal->getStdout()->writeAsync(<<getStdout()->writeAllAsync(<< schema.hack @@ -49,7 +49,7 @@ protected function getSupportedOptions(): vec { if ($match === null) { /* HHAST_IGNORE_ERROR[DontAwaitInALoop] */ await $terminal->getStderr() - ->writeAsync("Expected file name matching [database_name].sql, {$file} does not match"); + ->writeAllAsync("Expected file name matching [database_name].sql, {$file} does not match"); return 1; } @@ -59,7 +59,7 @@ protected function getSupportedOptions(): vec { if ($contents === false) { /* HHAST_IGNORE_ERROR[DontAwaitInALoop] */ - await $terminal->getStderr()->writeAsync("File could not be loaded: {$contents}"); + await $terminal->getStderr()->writeAllAsync("File could not be loaded: {$contents}"); return 1; } @@ -105,7 +105,7 @@ protected function getSupportedOptions(): vec { . $generated; - await $terminal->getStdout()->writeAsync($generated); + await $terminal->getStdout()->writeAllAsync($generated); return 0; } } diff --git a/src/Logger.php b/src/Logger.php index 20ddbc4..6d20a89 100644 --- a/src/Logger.php +++ b/src/Logger.php @@ -20,8 +20,8 @@ public static function log(Verbosity $verbosity, string $message): void { protected static function write(string $message): void { if (self::$handle is nonnull) { - /*HHAST_FIXME[DontUseAsioJoin]*/ - \HH\Asio\join(self::$handle->writeAsync($message)); + /*HHAST_FIXME[DontUseAsioJoin]*/ + \HH\Asio\join(self::$handle->writeAllAsync($message)); } else { \error_log($message); } diff --git a/src/Parser/CreateTableParser.php b/src/Parser/CreateTableParser.php index a18b530..6ee6284 100644 --- a/src/Parser/CreateTableParser.php +++ b/src/Parser/CreateTableParser.php @@ -352,9 +352,7 @@ private function nextTokenIs(vec $tokens, string $val): bool { return Str\uppercase($tokens[0]) === $val; } - private function parseCreateDefinition( - inout vec $tokens, - ): shape( + private function parseCreateDefinition(inout vec $tokens): shape( 'fields' => vec, 'indexes' => vec, ) { @@ -521,6 +519,9 @@ private function parseFieldOrKey( # not currently handled return; + default: + # any other tokens fall through to be parsed below + break; } $fields[] = $this->parseField($tokens); @@ -881,8 +882,10 @@ private function extractTokens(string $sql, vec<(int, int)> $source_map): vec { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/InsertQueryTest.php b/tests/InsertQueryTest.php index fe431db..b668c03 100644 --- a/tests/InsertQueryTest.php +++ b/tests/InsertQueryTest.php @@ -15,7 +15,7 @@ final class InsertQueryTest extends HackTest { $pool = new AsyncMysqlConnectionPool(darray[]); static::$conn = await $pool->connect('example', 1, 'db1', '', ''); // black hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/JSONFunctionTest.hack b/tests/JSONFunctionTest.hack index 37a5dfb..e1e3a23 100644 --- a/tests/JSONFunctionTest.hack +++ b/tests/JSONFunctionTest.hack @@ -20,7 +20,7 @@ final class JSONFunctionTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/JoinQueryTest.php b/tests/JoinQueryTest.php index 233814c..ae84aaf 100644 --- a/tests/JoinQueryTest.php +++ b/tests/JoinQueryTest.php @@ -91,8 +91,9 @@ final class JoinQueryTest extends HackTest { public async function testLeftJoin(): Awaitable { $conn = static::$conn as nonnull; - $results = - await $conn->query('SELECT id, table_4_id FROM table3 LEFT OUTER JOIN association_table ON id=table_3_id'); + $results = await $conn->query( + 'SELECT id, table_4_id FROM table3 LEFT OUTER JOIN association_table ON id=table_3_id', + ); expect($results->rows())->toBeSame(vec[ dict['id' => 1, 'table_4_id' => 1000], dict['id' => 1, 'table_4_id' => 1001], @@ -151,7 +152,7 @@ final class JoinQueryTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/MultiQueryTest.php b/tests/MultiQueryTest.php index e7d0ed6..9e674d4 100644 --- a/tests/MultiQueryTest.php +++ b/tests/MultiQueryTest.php @@ -91,7 +91,7 @@ final class MultiQueryTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/SQLFunctionTest.php b/tests/SQLFunctionTest.php index f7f14a1..22c986f 100644 --- a/tests/SQLFunctionTest.php +++ b/tests/SQLFunctionTest.php @@ -357,7 +357,7 @@ final class SQLFunctionTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/SelectClauseTest.php b/tests/SelectClauseTest.php index 921a9b3..792d55b 100644 --- a/tests/SelectClauseTest.php +++ b/tests/SelectClauseTest.php @@ -13,7 +13,7 @@ final class SelectClauseTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/SelectExpressionTest.php b/tests/SelectExpressionTest.php index fe8e6c0..944ddd5 100644 --- a/tests/SelectExpressionTest.php +++ b/tests/SelectExpressionTest.php @@ -22,7 +22,7 @@ final class SelectExpressionTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> @@ -46,8 +46,9 @@ final class SelectExpressionTest extends HackTest { public async function testSelectExpressions(): Awaitable { $conn = static::$conn as nonnull; - $results = - await $conn->query('SELECT id, group_id as my_fav_group_id, id*1000 as math FROM table3 WHERE group_id=6'); + $results = await $conn->query( + 'SELECT id, group_id as my_fav_group_id, id*1000 as math FROM table3 WHERE group_id=6', + ); expect($results->rows())->toBeSame( vec[ dict['id' => 4, 'my_fav_group_id' => 6, 'math' => 4000], @@ -199,8 +200,9 @@ final class SelectExpressionTest extends HackTest { // weird this is even valid SQL, and possibly pedantic, but this demonstrates a lot of how // case statements are implemented such that it doesn't blow up on the second THEN or second CASE - $results = - await $conn->query("SELECT CASE WHEN 4 = CASE WHEN 1 = 2 THEN 3 ELSE 4 END THEN 'yes' ELSE 'no' END"); + $results = await $conn->query( + "SELECT CASE WHEN 4 = CASE WHEN 1 = 2 THEN 3 ELSE 4 END THEN 'yes' ELSE 'no' END", + ); expect($results->rows())->toBeSame( vec[ dict["CASE WHEN 4 = CASE WHEN 1 = 2 THEN 3 ELSE 4 END THEN 'yes' ELSE 'no' END" => 'yes'], @@ -242,7 +244,17 @@ final class SelectExpressionTest extends HackTest { ); expect($results->rows())->toBeSame( vec[ - dict['test1' => 1, 'test2' => 1, 'test3' => 1, 'test4' => 1, 'test5' => 1, 'test6' => 1, 'test7' => 0, 'test8' => 1, 'test9' => 1], + dict[ + 'test1' => 1, + 'test2' => 1, + 'test3' => 1, + 'test4' => 1, + 'test5' => 1, + 'test6' => 1, + 'test7' => 0, + 'test8' => 1, + 'test9' => 1, + ], ], ); } @@ -331,8 +343,9 @@ final class SelectExpressionTest extends HackTest { public async function testNotParens(): Awaitable { $conn = static::$conn as nonnull; - $results = - await $conn->query("SELECT id FROM table3 WHERE group_id=12345 AND NOT (name='name1' OR name='name3')"); + $results = await $conn->query( + "SELECT id FROM table3 WHERE group_id=12345 AND NOT (name='name1' OR name='name3')", + ); expect($results->rows())->toBeSame(vec[ dict['id' => 2], ]); diff --git a/tests/SelectQueryValidatorTest.php b/tests/SelectQueryValidatorTest.php index 35caeca..106a683 100644 --- a/tests/SelectQueryValidatorTest.php +++ b/tests/SelectQueryValidatorTest.php @@ -15,7 +15,7 @@ final class SelectQueryValidatorTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initVitessAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/UpdateQueryTest.php b/tests/UpdateQueryTest.php index 645211a..88aa1f5 100644 --- a/tests/UpdateQueryTest.php +++ b/tests/UpdateQueryTest.php @@ -92,7 +92,7 @@ final class UpdateQueryTest extends HackTest { $results = await $conn->query("SELECT * FROM table3 WHERE name='testupdated'"); expect($results->rows())->toBeSame( vec[ - dict['id' => 77, 'group_id' => 0, 'name' => 'testupdated'] + dict['id' => 77, 'group_id' => 0, 'name' => 'testupdated'], ], ); } @@ -121,7 +121,7 @@ final class UpdateQueryTest extends HackTest { public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initAsync(); // block hole logging - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> diff --git a/tests/UpdateQueryValidatorTest.php b/tests/UpdateQueryValidatorTest.php index 154af7c..2ae578e 100644 --- a/tests/UpdateQueryValidatorTest.php +++ b/tests/UpdateQueryValidatorTest.php @@ -6,14 +6,14 @@ use type Facebook\HackTest\HackTest; final class UpdateQueryValidatorTest extends HackTest { - private static ?AsyncMysqlConnection $conn; + private static ?AsyncMysqlConnection $conn; <<__Override>> public static async function beforeFirstTestAsync(): Awaitable { static::$conn = await SharedSetup::initVitessAsync(); - // block hole logging - // ? copied from SelectQueryValidatorTest.php, not sure what that means. - Logger::setHandle(new \Facebook\CLILib\TestLib\StringOutput()); + // block hole logging + // ? copied from SelectQueryValidatorTest.php, not sure what that means. + Logger::setHandle(new \HH\Lib\IO\MemoryHandle()); } <<__Override>> @@ -23,28 +23,28 @@ final class UpdateQueryValidatorTest extends HackTest { QueryContext::$strictSQLMode = false; } - public async function testUpdateChangesPrimaryVindex(): Awaitable { + public async function testUpdateChangesPrimaryVindex(): Awaitable { $conn = static::$conn as nonnull; - $unsupported_test_cases = vec[ - 'update vt_table1 set id=1 where id=1', - 'update vt_table2 set vt_table1_id=1 where id=1' - ]; + $unsupported_test_cases = vec[ + 'update vt_table1 set id=1 where id=1', + 'update vt_table2 set vt_table1_id=1 where id=1', + ]; - foreach($unsupported_test_cases as $sql) { + foreach ($unsupported_test_cases as $sql) { expect(() ==> $conn->query($sql))->toThrow( SQLFakeVitessQueryViolation::class, 'Vitess query validation error: unsupported: update changes primary vindex column', ); - } + } - $supported_test_cases = vec[ - "update vt_table1 set name='foo' where id = 1" - ]; + $supported_test_cases = vec[ + "update vt_table1 set name='foo' where id = 1", + ]; foreach ($supported_test_cases as $sql) { expect(() ==> $conn->query($sql))->notToThrow(SQLFakeVitessQueryViolation::class); } - - } + + } }