Test coverage
This commit is contained in:
parent
0ed7a34948
commit
99c5ac9697
20
phpunit.xml
Normal file
20
phpunit.xml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<phpunit
|
||||||
|
colors="true"
|
||||||
|
stopOnFailure="false"
|
||||||
|
beStrictAboutTestsThatDoNotTestAnything="true"
|
||||||
|
>
|
||||||
|
<filter>
|
||||||
|
<whitelist>
|
||||||
|
<directory suffix=".php">src</directory>
|
||||||
|
</whitelist>
|
||||||
|
</filter>
|
||||||
|
<testsuites>
|
||||||
|
<testsuite name="PHPKilo">
|
||||||
|
<directory>tests</directory>
|
||||||
|
</testsuite>
|
||||||
|
</testsuites>
|
||||||
|
<logging>
|
||||||
|
<log type="coverage-html" target="coverage"/>
|
||||||
|
</logging>
|
||||||
|
</phpunit>
|
@ -6,6 +6,8 @@ namespace Aviat\Kilo\Enum;
|
|||||||
* Just a namespace for C language constants
|
* Just a namespace for C language constants
|
||||||
*/
|
*/
|
||||||
class C {
|
class C {
|
||||||
|
use ConstList;
|
||||||
|
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
// ! Misc I/O constants
|
// ! Misc I/O constants
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
@ -6,6 +6,8 @@ namespace Aviat\Kilo\Enum;
|
|||||||
* ANSI Color escape sequences
|
* ANSI Color escape sequences
|
||||||
*/
|
*/
|
||||||
class Color {
|
class Color {
|
||||||
|
use ConstList;
|
||||||
|
|
||||||
// Foreground colors
|
// Foreground colors
|
||||||
public const FG_BLACK = 30;
|
public const FG_BLACK = 30;
|
||||||
public const FG_RED = 31;
|
public const FG_RED = 31;
|
||||||
|
12
src/Enum/ConstList.php
Normal file
12
src/Enum/ConstList.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Aviat\Kilo\Enum;
|
||||||
|
|
||||||
|
use ReflectionClass;
|
||||||
|
|
||||||
|
trait ConstList {
|
||||||
|
public static function getConstList(): array
|
||||||
|
{
|
||||||
|
return (new ReflectionClass(static::class))->getConstants();
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,8 @@
|
|||||||
namespace Aviat\Kilo\Enum;
|
namespace Aviat\Kilo\Enum;
|
||||||
|
|
||||||
class Highlight {
|
class Highlight {
|
||||||
|
use ConstList;
|
||||||
|
|
||||||
public const NORMAL = 0;
|
public const NORMAL = 0;
|
||||||
public const COMMENT = 1;
|
public const COMMENT = 1;
|
||||||
public const ML_COMMENT = 2;
|
public const ML_COMMENT = 2;
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace Aviat\Kilo\Enum;
|
namespace Aviat\Kilo\Enum;
|
||||||
|
|
||||||
use ReflectionClass;
|
|
||||||
|
|
||||||
class Key {
|
class Key {
|
||||||
|
use ConstList;
|
||||||
|
|
||||||
public const ARROW_DOWN = 'ARROW_DOWN';
|
public const ARROW_DOWN = 'ARROW_DOWN';
|
||||||
public const ARROW_LEFT = 'ARROW_LEFT';
|
public const ARROW_LEFT = 'ARROW_LEFT';
|
||||||
public const ARROW_RIGHT = 'ARROW_RIGHT';
|
public const ARROW_RIGHT = 'ARROW_RIGHT';
|
||||||
@ -17,9 +17,4 @@ class Key {
|
|||||||
public const HOME_KEY = 'HOME';
|
public const HOME_KEY = 'HOME';
|
||||||
public const PAGE_DOWN = 'PAGE_DOWN';
|
public const PAGE_DOWN = 'PAGE_DOWN';
|
||||||
public const PAGE_UP = 'PAGE_UP';
|
public const PAGE_UP = 'PAGE_UP';
|
||||||
|
|
||||||
public static function getConstList(): array
|
|
||||||
{
|
|
||||||
return (new ReflectionClass(static::class))->getConstants();
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -16,6 +16,7 @@ use Aviat\Kilo\Enum\{
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @TODO fix
|
* @TODO fix
|
||||||
|
* @codeCoverageIgnore
|
||||||
*/
|
*/
|
||||||
function get_cursor_position()
|
function get_cursor_position()
|
||||||
{
|
{
|
||||||
@ -37,6 +38,12 @@ function get_cursor_position()
|
|||||||
return [$rows, $cols];
|
return [$rows, $cols];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the size of the current terminal window
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
function get_window_size()
|
function get_window_size()
|
||||||
{
|
{
|
||||||
$ffi = get_ffi();
|
$ffi = get_ffi();
|
||||||
@ -103,7 +110,7 @@ function is_ascii(string $single_char): bool
|
|||||||
function is_cntrl(string $char): bool
|
function is_cntrl(string $char): bool
|
||||||
{
|
{
|
||||||
$c = ord($char);
|
$c = ord($char);
|
||||||
return is_ascii($char) && ( $c < 0x20 || $c === 0x7f );
|
return is_ascii($char) && ( $c === 0x7f || $c < 0x20 );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -174,6 +181,7 @@ function is_separator(string $char): bool
|
|||||||
/**
|
/**
|
||||||
* Pull input from the stdin stream.
|
* Pull input from the stdin stream.
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
* @param int $len
|
* @param int $len
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
@ -189,6 +197,7 @@ function read_stdin(int $len = 128): string
|
|||||||
/**
|
/**
|
||||||
* Write to the stdout stream
|
* Write to the stdout stream
|
||||||
*
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
* @param string $str
|
* @param string $str
|
||||||
* @param int|NULL $len
|
* @param int|NULL $len
|
||||||
* @return int
|
* @return int
|
||||||
@ -205,6 +214,11 @@ function write_stdout(string $str, int $len = NULL): int
|
|||||||
return $res;
|
return $res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
* @param int $len
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
function read_stdout(int $len = 128): string
|
function read_stdout(int $len = 128): string
|
||||||
{
|
{
|
||||||
$handle = fopen('php://stdout', 'rb');
|
$handle = fopen('php://stdout', 'rb');
|
||||||
@ -234,14 +248,16 @@ function array_replace_range(array &$array, int $offset, int $length, $value):vo
|
|||||||
|
|
||||||
$replacement = array_fill(0, $length, $value);
|
$replacement = array_fill(0, $length, $value);
|
||||||
array_splice($array, $offset, $length, $replacement);
|
array_splice($array, $offset, $length, $replacement);
|
||||||
|
|
||||||
/* $end = $offset + $length;
|
|
||||||
for ($i = $offset; $i < $end; $i++)
|
|
||||||
{
|
|
||||||
$array[$i] = $value;
|
|
||||||
} */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the string $haystack contain $str, optionally searching from $offset?
|
||||||
|
*
|
||||||
|
* @param string $haystack
|
||||||
|
* @param string $str
|
||||||
|
* @param int|null $offset
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
function str_contains(string $haystack, string $str, ?int $offset = NULL): bool
|
function str_contains(string $haystack, string $str, ?int $offset = NULL): bool
|
||||||
{
|
{
|
||||||
if (empty($str))
|
if (empty($str))
|
||||||
|
25
tests/Enum/ConstListTest.php
Normal file
25
tests/Enum/ConstListTest.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Aviat\Kilo\Tests\Enum;
|
||||||
|
|
||||||
|
use Aviat\Kilo\Enum\ConstList;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class ConstListTest extends TestCase {
|
||||||
|
public function testGetConstList(): void
|
||||||
|
{
|
||||||
|
$testClass = new class {
|
||||||
|
use ConstList;
|
||||||
|
|
||||||
|
public const foo = 'foo';
|
||||||
|
public const bar = 'bar';
|
||||||
|
};
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
'foo' => 'foo',
|
||||||
|
'bar' => 'bar',
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $testClass::getConstList());
|
||||||
|
}
|
||||||
|
}
|
@ -2,10 +2,22 @@
|
|||||||
|
|
||||||
namespace Aviat\Kilo\Tests;
|
namespace Aviat\Kilo\Tests;
|
||||||
|
|
||||||
|
use Aviat\Kilo\Enum\Color;
|
||||||
|
use Aviat\Kilo\Enum\Highlight;
|
||||||
use PHPUnit\Framework\TestCase;
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
use function Aviat\Kilo\array_replace_range;
|
||||||
|
use function Aviat\Kilo\ctrl_key;
|
||||||
|
use function Aviat\Kilo\get_file_syntax_map;
|
||||||
use function Aviat\Kilo\get_window_size;
|
use function Aviat\Kilo\get_window_size;
|
||||||
use function Aviat\Kilo\is_ascii;
|
use function Aviat\Kilo\is_ascii;
|
||||||
|
use function Aviat\Kilo\is_cntrl;
|
||||||
|
use function Aviat\Kilo\is_digit;
|
||||||
|
use function Aviat\Kilo\is_separator;
|
||||||
|
use function Aviat\Kilo\is_space;
|
||||||
|
use function Aviat\Kilo\str_contains;
|
||||||
|
use function Aviat\Kilo\syntax_to_color;
|
||||||
|
use function Aviat\Kilo\tabs_to_spaces;
|
||||||
|
|
||||||
class FunctionTest extends TestCase {
|
class FunctionTest extends TestCase {
|
||||||
public function test_get_window_size(): void
|
public function test_get_window_size(): void
|
||||||
@ -20,5 +32,125 @@ class FunctionTest extends TestCase {
|
|||||||
$this->assertFalse(is_ascii('©'));
|
$this->assertFalse(is_ascii('©'));
|
||||||
$this->assertFalse(is_ascii("\x80"));
|
$this->assertFalse(is_ascii("\x80"));
|
||||||
$this->assertTrue(is_ascii('a'));
|
$this->assertTrue(is_ascii('a'));
|
||||||
|
$this->assertTrue(is_ascii("\x7b"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_ctrl_key(): void
|
||||||
|
{
|
||||||
|
$this->assertEquals(-1, ctrl_key("\x80"));
|
||||||
|
|
||||||
|
$this->assertEquals(0x01, ctrl_key('a'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_is_cntrl(): void
|
||||||
|
{
|
||||||
|
for ($i = 0x0; $i < 0x20; $i++)
|
||||||
|
{
|
||||||
|
$char = chr($i);
|
||||||
|
$this->assertTrue(is_cntrl($char), 'Should be a control character');
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($n = 0x20; $n < 0x7f; $n++)
|
||||||
|
{
|
||||||
|
$char = chr($n);
|
||||||
|
$this->assertFalse(is_cntrl($char), 'Should not be a control character');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Escape, code 7f, is an outlier
|
||||||
|
$this->assertTrue(is_cntrl(chr(0x7f)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_is_space(): void
|
||||||
|
{
|
||||||
|
$this->assertFalse(is_space("\x80"), 'Non-ascii character is not considered a space');
|
||||||
|
|
||||||
|
foreach ([' ', "\t", "\n", "\r", "\xa", "\xb", "\xc"] as $char)
|
||||||
|
{
|
||||||
|
$this->assertTrue(is_space($char), 'Should be considered a space character');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_is_digit(): void
|
||||||
|
{
|
||||||
|
$this->assertFalse(is_separator("\x80"), 'Non-ascii character is not a digit');
|
||||||
|
|
||||||
|
$digits = str_split('01234567890');
|
||||||
|
foreach ($digits as $digit)
|
||||||
|
{
|
||||||
|
$this->assertTrue(is_digit($digit));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_is_separator(): void
|
||||||
|
{
|
||||||
|
$this->assertFalse(is_separator("\x80"), 'Non-ascii character is not a separator');
|
||||||
|
|
||||||
|
$chars = str_split(',.()+-/*=~%<>[];');
|
||||||
|
foreach ($chars as $char)
|
||||||
|
{
|
||||||
|
$this->assertTrue(is_separator($char), 'The character should be considered a separator');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Null byte is considered a separator
|
||||||
|
$this->assertTrue(is_separator("\0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_syntax_to_color(): void
|
||||||
|
{
|
||||||
|
// Nonsense input returns FG::White
|
||||||
|
$this->assertEquals(syntax_to_color(999), Color::FG_WHITE);
|
||||||
|
|
||||||
|
$this->assertNotEquals(syntax_to_color(Highlight::OPERATOR), Color::FG_WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_get_file_syntax_map(): void
|
||||||
|
{
|
||||||
|
$this->assertNotEmpty(get_file_syntax_map());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_str_contains(): void
|
||||||
|
{
|
||||||
|
// Search from string offset
|
||||||
|
$this->assertTrue(str_contains(' vcd', 'vcd', 2));
|
||||||
|
|
||||||
|
$this->assertFalse(str_contains('', "\0"));
|
||||||
|
|
||||||
|
// An empty search string returns false
|
||||||
|
$this->assertFalse(str_contains('', ''));
|
||||||
|
|
||||||
|
$this->assertTrue(str_contains('alphabet', 'phab'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_tabs_to_spaces(): void
|
||||||
|
{
|
||||||
|
$original = "\t\t\t{";
|
||||||
|
$this->assertFalse(str_contains(tabs_to_spaces($original), "\t"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_array_replace_range_length_1(): void
|
||||||
|
{
|
||||||
|
$original = [
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f'
|
||||||
|
];
|
||||||
|
|
||||||
|
$expected = ['a', 'b', 'c', 'foo', 'e', 'f'];
|
||||||
|
|
||||||
|
array_replace_range($original, 3, 1, 'foo');
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $original);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_array_replace_range_length_gt_1(): void
|
||||||
|
{
|
||||||
|
$original = [
|
||||||
|
'a', 'b', 'c', 'd', 'e', 'f'
|
||||||
|
];
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
'a', 'foo', 'foo', 'foo', 'e', 'f'
|
||||||
|
];
|
||||||
|
|
||||||
|
array_replace_range($original, 1, 3, 'foo');
|
||||||
|
$this->assertEquals($expected, $original);
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user