From 75ac608f9c764d3ed1ea751b0ba38418041a10ed Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Tue, 30 Jun 2020 15:58:18 -0700 Subject: [PATCH] Update tests for HSL IO v0.2 (#32) * Update tests for HSL IO v0.2 I think the logic being tested was bad; there are two classes of issues here: - `IO\MemoryHandle` works like a read-write file. `TestLib\StringInput` was... unique. Use pipes where we need funky stuff. In particular, if it's closed, it can't be read from. - Checking `isEndOfFile()` before echoing the `> ` prompt was a bug and undefined behavior really - consistently prompt before attempting to get input * disable hhast testing temporarily - circular dependency * Guarantee ordering for '(Before|After)Start' * comment out full hhast if block * Require HHVM 4.60 Dependencies need it anyway; even though it's only for dev-depends, don't want to support a version that can't be tested --- .travis.sh | 7 ++-- .travis.yml | 2 +- composer.json | 2 +- tests/InteractivityTest.hack | 67 ++++++++++++++++++++++++++---------- tests/TestCLITrait.hack | 3 +- 5 files changed, 57 insertions(+), 24 deletions(-) diff --git a/.travis.sh b/.travis.sh index fc4e377..dbfea28 100755 --- a/.travis.sh +++ b/.travis.sh @@ -14,6 +14,7 @@ composer install hh_client vendor/bin/hacktest tests/ -if !(hhvm --version | grep -q -- -dev); then - vendor/bin/hhast-lint -fi +# TEMPORARY: circular dependency for HSL-IO v0.2 upgrade +#if !(hhvm --version | grep -q -- -dev); then +# vendor/bin/hhast-lint +#fi diff --git a/.travis.yml b/.travis.yml index 51bdc09..307fa40 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ sudo: required language: generic services: docker env: -- HHVM_VERSION=4.58-latest +- HHVM_VERSION=4.60-latest - HHVM_VERSION=latest - HHVM_VERSION=nightly install: diff --git a/composer.json b/composer.json index fa6e15f..6cbad58 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ } }, "require": { - "hhvm": "^4.58", + "hhvm": "^4.60", "hhvm/hsl": "^4.0", "hhvm/type-assert": "^4.0", "hhvm/hsl-experimental": "^4.58.0rc1", diff --git a/tests/InteractivityTest.hack b/tests/InteractivityTest.hack index 2eb470d..e4cd325 100644 --- a/tests/InteractivityTest.hack +++ b/tests/InteractivityTest.hack @@ -14,7 +14,12 @@ use function Facebook\FBExpect\expect; final class InteractivityTest extends TestCase { private function getCLI( - ): (TestCLIWithoutArguments, IO\MemoryHandle, IO\MemoryHandle, IO\MemoryHandle) { + ): ( + TestCLIWithoutArguments, + IO\MemoryHandle, + IO\MemoryHandle, + IO\MemoryHandle, + ) { $stdin = new IO\MemoryHandle(); $stdout = new IO\MemoryHandle(); $stderr = new IO\MemoryHandle(); @@ -30,33 +35,53 @@ final class InteractivityTest extends TestCase { $in->close(); $ret = await $cli->mainAsync(); expect($ret)->toBeSame(0); - expect($out->getBuffer())->toBeSame(''); + expect($out->getBuffer())->toBeSame('> '); expect($err->getBuffer())->toBeSame(''); } public async function testSingleCommandBeforeStart(): Awaitable { - list($cli, $in, $out, $err) = $this->getCLI(); - $in->appendToBuffer("echo hello, world\n"); + // Don't use the MemoryHandle because reading from a closed handle + // doesn't make sense - a pipe is both necessary, and a better + // representation of 'echo foo | myprog' + list($in_r, $in) = IO\pipe(); + $out = new IO\MemoryHandle(); + $err = new IO\MemoryHandle(); + $cli = new TestCLIWithoutArguments( + vec[__FILE__, '--interactive'], + new Terminal($in_r, $out, $err), + ); + + await $in->writeAllAsync("echo hello, world\n"); $in->close(); $ret = await $cli->mainAsync(); - expect($err->getBuffer())->toBeSame(''); - expect($out->getBuffer())->toBeSame("> hello, world\n"); - expect($ret)->toBeSame(0); + $in_r->close(); + + expect($err->getBuffer())->toEqual(''); + expect($out->getBuffer())->toEqual("> hello, world\n> "); + expect($ret)->toEqual(0); } public async function testSingleCommandAfterStart(): Awaitable { - list($cli, $in, $out, $err) = $this->getCLI(); + list($in_r, $in) = IO\pipe(); + list($out, $out_w) = IO\pipe(); + $err = new IO\MemoryHandle(); + $cli = new TestCLIWithoutArguments( + vec[__FILE__, '--interactive'], + new Terminal($in_r, $out_w, $err), + ); concurrent { $ret = await $cli->mainAsync(); await async { - await \HH\Asio\later(); - expect($out->getBuffer())->toBeSame('> '); - $out->reset(); - $in->appendToBuffer("exit 123\n"); + expect(await $out->readAsync())->toEqual('> '); + await $in->writeAllAsync("exit 123\n"); + $in->close(); }; } + $in_r->close(); + $out_w->close(); expect($ret)->toBeSame(123); - expect($out->getBuffer())->toBeSame(''); + expect(await $out->readAllAsync())->toBeSame(''); + $out->close(); } public async function testMultipleCommandBeforeStart(): Awaitable { @@ -64,7 +89,6 @@ final class InteractivityTest extends TestCase { $in->appendToBuffer("echo hello, world\n"); $in->appendToBuffer("echo foo bar\n"); $in->appendToBuffer("exit 123\n"); - $in->close(); $ret = await $cli->mainAsync(); expect($err->getBuffer())->toBeSame(''); expect($out->getBuffer())->toBeSame("> hello, world\n> foo bar\n> "); @@ -72,7 +96,13 @@ final class InteractivityTest extends TestCase { } public async function testMultipleCommandsSequentially(): Awaitable { - list($cli, $in, $out, $err) = $this->getCLI(); + list($in_r, $in) = IO\pipe(); + $out = new IO\MemoryHandle(); + $err = new IO\MemoryHandle(); + $cli = new TestCLIWithoutArguments( + vec[__FILE__, '--interactive'], + new Terminal($in_r, $out, $err), + ); concurrent { $ret = await $cli->mainAsync(); await async { @@ -80,18 +110,19 @@ final class InteractivityTest extends TestCase { expect($out->getBuffer())->toBeSame('> '); $out->reset(); - $in->appendToBuffer("echo foo bar\n"); + await $in->writeAllAsync("echo foo bar\n"); await \HH\Asio\later(); expect($out->getBuffer())->toBeSame("foo bar\n> "); $out->reset(); - $in->appendToBuffer("echo herp derp\n"); + await $in->writeAllAsync("echo herp derp\n"); await \HH\Asio\later(); expect($out->getBuffer())->toBeSame("herp derp\n> "); $out->reset(); - $in->appendToBuffer("exit 42\n"); + await $in->writeAllAsync("exit 42\n"); + $in->close(); }; } expect($ret)->toBeSame(42); diff --git a/tests/TestCLITrait.hack b/tests/TestCLITrait.hack index 0a25296..a4093e0 100644 --- a/tests/TestCLITrait.hack +++ b/tests/TestCLITrait.hack @@ -68,8 +68,8 @@ trait TestCLITrait { $in = $this->getStdin(); $out = $this->getStdout(); $err = $this->getStderr(); + await $out->writeAsync('> '); foreach((new IO\BufferedReader($in))->linesIterator() await as $line) { - await $out->writeAsync('> '); $sep = Str\search($line, ' '); if ($sep === null) { await $err->writeAsync("Usage: (exit |echo foo bar ....\n"); @@ -92,6 +92,7 @@ trait TestCLITrait { await $err->writeAsync("Invalid command\n"); return 1; } + await $out->writeAsync('> '); } return 0; }