mirror of
https://github.com/danog/endtoend-test-psl.git
synced 2024-11-30 04:39:48 +01:00
[DataStructure] Introduce the DataStructure component (#53)
This commit is contained in:
parent
f60c10629d
commit
1bebacb3ce
@ -24,9 +24,9 @@ namespace Psl\Arr;
|
||||
*
|
||||
* @psalm-param array<Tk, Tv> $array
|
||||
* @psalm-param Tk $index
|
||||
* @psalm-param Tv|null $default
|
||||
* @psalm-param Tv $default
|
||||
*
|
||||
* @psalm-return Tv|null
|
||||
* @psalm-return Tv
|
||||
*
|
||||
* @psalm-pure
|
||||
*/
|
||||
|
139
src/Psl/DataStructure/PriorityQueue.php
Normal file
139
src/Psl/DataStructure/PriorityQueue.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Psl\Arr;
|
||||
use Psl\Math;
|
||||
|
||||
/**
|
||||
* @psalm-template T
|
||||
*
|
||||
* @implements PriorityQueueInterface<T>
|
||||
*/
|
||||
final class PriorityQueue implements PriorityQueueInterface
|
||||
{
|
||||
/**
|
||||
* @psalm-var array<int, list<T>>
|
||||
*/
|
||||
private array $queue = [];
|
||||
|
||||
/**
|
||||
* Adds a node to the queue.
|
||||
*
|
||||
* @psalm-param T $node
|
||||
*/
|
||||
public function enqueue($node, int $priority = 0): void
|
||||
{
|
||||
$nodes = $this->queue[$priority] ?? [];
|
||||
$nodes[] = $node;
|
||||
|
||||
$this->queue[$priority] = $nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the node at the head of this queue,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
if (0 === $this->count()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Retrieve the highest priority.
|
||||
$priority = Math\max(Arr\keys($this->queue)) ?? 0;
|
||||
|
||||
// Retrieve the list of nodes with the priority `$priority`.
|
||||
$nodes = Arr\idx($this->queue, $priority, []);
|
||||
|
||||
// Retrieve the first node of the list.
|
||||
return Arr\first($nodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the node at the head of this queue,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function pull()
|
||||
{
|
||||
if (0 === $this->count()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @psalm-suppress MissingThrowsDocblock - the queue is not empty */
|
||||
return $this->dequeue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues a node from the queue.
|
||||
*
|
||||
* @psalm-return T
|
||||
*
|
||||
* @throws Psl\Exception\InvariantViolationException If the Queue is invalid.
|
||||
*/
|
||||
public function dequeue()
|
||||
{
|
||||
Psl\invariant(0 !== $this->count(), 'Cannot dequeue a node from an empty Queue.');
|
||||
|
||||
/**
|
||||
* Peeking into a non-empty queue always results in a value.
|
||||
*
|
||||
* @psalm-var T $node
|
||||
*/
|
||||
$node = $this->peek();
|
||||
|
||||
$this->drop();
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
private function drop(): void
|
||||
{
|
||||
/**
|
||||
* Retrieve the highest priority.
|
||||
*
|
||||
* @var int $priority
|
||||
*/
|
||||
$priority = Math\max(Arr\keys($this->queue));
|
||||
|
||||
/**
|
||||
* Retrieve the list of nodes with the priority `$priority`.
|
||||
*
|
||||
* @psalm-suppress MissingThrowsDocblock
|
||||
*/
|
||||
$nodes = Arr\at($this->queue, $priority);
|
||||
|
||||
// If the list contained only this node,
|
||||
// remove the list of nodes with priority `$priority`.
|
||||
if (1 === Arr\count($nodes)) {
|
||||
unset($this->queue[$priority]);
|
||||
} else {
|
||||
/**
|
||||
* otherwise, drop the first node.
|
||||
*
|
||||
* @psalm-suppress MissingThrowsDocblock
|
||||
*/
|
||||
$this->queue[$priority] = Arr\values(Arr\drop($nodes, 1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the nodes in the queue.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
$count = 0;
|
||||
foreach ($this->queue as $priority => $list) {
|
||||
$count += Arr\count($list);
|
||||
}
|
||||
|
||||
return $count;
|
||||
}
|
||||
}
|
23
src/Psl/DataStructure/PriorityQueueInterface.php
Normal file
23
src/Psl/DataStructure/PriorityQueueInterface.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* @template T
|
||||
*
|
||||
* @extends QueueInterface<T>
|
||||
*/
|
||||
interface PriorityQueueInterface extends QueueInterface
|
||||
{
|
||||
/**
|
||||
* Adds a node to the queue.
|
||||
*
|
||||
* @psalm-param T $node
|
||||
*/
|
||||
public function enqueue($node, int $priority = 0): void;
|
||||
}
|
85
src/Psl/DataStructure/Queue.php
Normal file
85
src/Psl/DataStructure/Queue.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Psl\Arr;
|
||||
|
||||
/**
|
||||
* A basic implementation of a queue data structure ( FIFO ).
|
||||
*
|
||||
* @psalm-template T
|
||||
*
|
||||
* @implements QueueInterface<T>
|
||||
*/
|
||||
final class Queue implements QueueInterface
|
||||
{
|
||||
/**
|
||||
* @psalm-var list<T>
|
||||
*/
|
||||
private array $queue = [];
|
||||
|
||||
/**
|
||||
* Adds a node to the queue.
|
||||
*
|
||||
* @psalm-param T $node
|
||||
*/
|
||||
public function enqueue($node): void
|
||||
{
|
||||
$this->queue[] = $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the node at the head of this queue,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
return Arr\first($this->queue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the node at the head of this queue,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function pull()
|
||||
{
|
||||
if (0 === $this->count()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @psalm-suppress MissingThrowsDocblock - we are sure that the queue is not empty. */
|
||||
return $this->dequeue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeues a node from the queue.
|
||||
*
|
||||
* @psalm-return T
|
||||
*
|
||||
* @throws Psl\Exception\InvariantViolationException If the Queue is invalid.
|
||||
*/
|
||||
public function dequeue()
|
||||
{
|
||||
Psl\invariant(0 !== $this->count(), 'Cannot dequeue a node from an empty Queue.');
|
||||
|
||||
$node = Arr\firstx($this->queue);
|
||||
$this->queue = Arr\values(Arr\drop($this->queue, 1));
|
||||
|
||||
return $node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the nodes in the queue.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return Arr\count($this->queue);
|
||||
}
|
||||
}
|
55
src/Psl/DataStructure/QueueInterface.php
Normal file
55
src/Psl/DataStructure/QueueInterface.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* An interface representing a queue data structure ( FIFO ).
|
||||
*
|
||||
* @template T
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics)
|
||||
*/
|
||||
interface QueueInterface extends Countable
|
||||
{
|
||||
/**
|
||||
* Adds a node to the queue.
|
||||
*
|
||||
* @psalm-param T $node
|
||||
*/
|
||||
public function enqueue($node): void;
|
||||
|
||||
/**
|
||||
* Retrieves, but does not remove, the node at the head of this queue,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function peek();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the node at the head of this queue,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function pull();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the node at the head of this queue.
|
||||
*
|
||||
* @psalm-return T
|
||||
*
|
||||
* @throws Psl\Exception\InvariantViolationException If the Queue is invalid.
|
||||
*/
|
||||
public function dequeue();
|
||||
|
||||
/**
|
||||
* Count the nodes in the queue.
|
||||
*/
|
||||
public function count(): int;
|
||||
}
|
85
src/Psl/DataStructure/Stack.php
Normal file
85
src/Psl/DataStructure/Stack.php
Normal file
@ -0,0 +1,85 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Psl\Arr;
|
||||
|
||||
/**
|
||||
* An basic implementation of a stack data structure ( LIFO ).
|
||||
*
|
||||
* @template T
|
||||
*
|
||||
* @implements StackInterface<T>
|
||||
*/
|
||||
final class Stack implements StackInterface
|
||||
{
|
||||
/**
|
||||
* @psalm-var list<T> $items
|
||||
*/
|
||||
private array $items = [];
|
||||
|
||||
/**
|
||||
* Adds an item to the stack.
|
||||
*
|
||||
* @psalm-param T $item
|
||||
*/
|
||||
public function push($item): void
|
||||
{
|
||||
$this->items[] = $item;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves, but does remove, the most recently added item that was not yet removed,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function peek()
|
||||
{
|
||||
return Arr\last($this->items);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves and removes the most recently added item that was not yet removed,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function pull()
|
||||
{
|
||||
if (0 === $this->count()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** @psalm-suppress MissingThrowsDocblock - the stack is not empty. */
|
||||
return $this->pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve and removes the most recently added item that was not yet removed.
|
||||
*
|
||||
* @psalm-return T
|
||||
*
|
||||
* @throws Psl\Exception\InvariantViolationException If the stack is empty.
|
||||
*/
|
||||
public function pop()
|
||||
{
|
||||
Psl\invariant(0 !== $this->count(), 'Cannot pop an item from an empty Stack.');
|
||||
|
||||
$tail = Arr\lastx($this->items);
|
||||
$this->items = Arr\values(Arr\take($this->items, $this->count() - 1));
|
||||
|
||||
return $tail;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the items in the stack.
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return Arr\count($this->items);
|
||||
}
|
||||
}
|
55
src/Psl/DataStructure/StackInterface.php
Normal file
55
src/Psl/DataStructure/StackInterface.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Countable;
|
||||
|
||||
/**
|
||||
* An interface representing a stack data structure ( LIFO ).
|
||||
*
|
||||
* @template T
|
||||
*
|
||||
* @see https://en.wikipedia.org/wiki/Stack_(abstract_data_type)
|
||||
*/
|
||||
interface StackInterface extends Countable
|
||||
{
|
||||
/**
|
||||
* Adds an item to the stack.
|
||||
*
|
||||
* @psalm-param T $item
|
||||
*/
|
||||
public function push($item): void;
|
||||
|
||||
/**
|
||||
* Retrieves, but does remove, the most recently added item that was not yet removed,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function peek();
|
||||
|
||||
/**
|
||||
* Retrieves and removes the most recently added item that was not yet removed,
|
||||
* or returns null if this queue is empty.
|
||||
*
|
||||
* @psalm-return null|T
|
||||
*/
|
||||
public function pull();
|
||||
|
||||
/**
|
||||
* Retrieve and removes the most recently added item that was not yet removed.
|
||||
*
|
||||
* @psalm-return T
|
||||
*
|
||||
* @throws Psl\Exception\InvariantViolationException If the stack is empty.
|
||||
*/
|
||||
public function pop();
|
||||
|
||||
/**
|
||||
* Count the items in the stack.
|
||||
*/
|
||||
public function count(): int;
|
||||
}
|
@ -63,7 +63,7 @@ final class Iterator implements SeekableIterator, Countable
|
||||
/**
|
||||
* @psalm-var (callable(): Generator<Tsk, Tsv, mixed, void>) $factory
|
||||
*/
|
||||
$factory = fn (): Generator => yield from $iterable;
|
||||
$factory = static fn (): Generator => yield from $iterable;
|
||||
|
||||
return new self($factory());
|
||||
}
|
||||
@ -77,7 +77,7 @@ final class Iterator implements SeekableIterator, Countable
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
Psl\invariant($this->valid(), 'Invalid iterator');
|
||||
Psl\invariant($this->valid(), 'The Iterator is invalid.');
|
||||
if (!Arr\contains_key($this->entries, $this->position)) {
|
||||
$this->progress();
|
||||
}
|
||||
@ -117,7 +117,7 @@ final class Iterator implements SeekableIterator, Countable
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
Psl\invariant($this->valid(), 'Invalid iterator');
|
||||
Psl\invariant($this->valid(), 'The Iterator is invalid.');
|
||||
if (!Arr\contains_key($this->entries, $this->position)) {
|
||||
$this->progress();
|
||||
}
|
||||
|
98
tests/Psl/DataStructure/PriorityQueueTest.php
Normal file
98
tests/Psl/DataStructure/PriorityQueueTest.php
Normal file
@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psl;
|
||||
use Psl\DataStructure;
|
||||
|
||||
final class PriorityQueueTest extends TestCase
|
||||
{
|
||||
public function testEnqueueAndDequeue(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
$queue->enqueue('hi', 1);
|
||||
$queue->enqueue('hey', 2);
|
||||
$queue->enqueue('hello', 3);
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->dequeue());
|
||||
self::assertCount(2, $queue);
|
||||
self::assertSame('hey', $queue->dequeue());
|
||||
self::assertCount(1, $queue);
|
||||
self::assertSame('hi', $queue->dequeue());
|
||||
}
|
||||
|
||||
public function testMultipleNodesWithSamePriority(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
$queue->enqueue('hi', 1);
|
||||
$queue->enqueue('hey', 1);
|
||||
$queue->enqueue('hello', 1);
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hi', $queue->dequeue());
|
||||
self::assertCount(2, $queue);
|
||||
self::assertSame('hey', $queue->dequeue());
|
||||
self::assertCount(1, $queue);
|
||||
self::assertSame('hello', $queue->dequeue());
|
||||
}
|
||||
|
||||
public function testPeekDoesNotRemoveTheNode(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
$queue->enqueue('hi', 1);
|
||||
$queue->enqueue('hey', 2);
|
||||
$queue->enqueue('hello', 3);
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->peek());
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->peek());
|
||||
}
|
||||
|
||||
public function testPeekReturnsNullWhenTheQueueIsEmpty(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
|
||||
self::assertCount(0, $queue);
|
||||
self::assertNull($queue->peek());
|
||||
}
|
||||
|
||||
public function testPullDoesRemoveTheNode(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
$queue->enqueue('hi', 1);
|
||||
$queue->enqueue('hey', 2);
|
||||
$queue->enqueue('hello', 3);
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->pull());
|
||||
self::assertCount(2, $queue);
|
||||
self::assertSame('hey', $queue->pull());
|
||||
self::assertCount(1, $queue);
|
||||
self::assertSame('hi', $queue->pull());
|
||||
self::assertCount(0, $queue);
|
||||
self::assertNull($queue->pull());
|
||||
}
|
||||
|
||||
public function testPullReturnsNullWhenTheQueueIsEmpty(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
|
||||
self::assertCount(0, $queue);
|
||||
self::assertNull($queue->pull());
|
||||
}
|
||||
|
||||
public function testDequeueThrowsWhenTheQueueIsEmpty(): void
|
||||
{
|
||||
$queue = new DataStructure\PriorityQueue();
|
||||
|
||||
$this->expectException(Psl\Exception\InvariantViolationException::class);
|
||||
$this->expectExceptionMessage('Cannot dequeue a node from an empty Queue.');
|
||||
|
||||
$queue->dequeue();
|
||||
}
|
||||
}
|
83
tests/Psl/DataStructure/QueueTest.php
Normal file
83
tests/Psl/DataStructure/QueueTest.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Psl\DataStructure;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class QueueTest extends TestCase
|
||||
{
|
||||
public function testEnqueueAndDequeue(): void
|
||||
{
|
||||
$queue = new DataStructure\Queue();
|
||||
$queue->enqueue('hello');
|
||||
$queue->enqueue('hey');
|
||||
$queue->enqueue('hi');
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->dequeue());
|
||||
self::assertCount(2, $queue);
|
||||
self::assertSame('hey', $queue->dequeue());
|
||||
self::assertCount(1, $queue);
|
||||
self::assertSame('hi', $queue->dequeue());
|
||||
}
|
||||
|
||||
public function testPeekDoesNotRemoveTheNode(): void
|
||||
{
|
||||
$queue = new DataStructure\Queue();
|
||||
$queue->enqueue('hello');
|
||||
$queue->enqueue('hey');
|
||||
$queue->enqueue('hi');
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->peek());
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->peek());
|
||||
}
|
||||
|
||||
public function testPeekReturnsNullWhenTheQueueIsEmpty(): void
|
||||
{
|
||||
$queue = new DataStructure\Queue();
|
||||
|
||||
self::assertCount(0, $queue);
|
||||
self::assertNull($queue->peek());
|
||||
}
|
||||
|
||||
public function testPullDoesRemoveTheNode(): void
|
||||
{
|
||||
$queue = new DataStructure\Queue();
|
||||
$queue->enqueue('hello');
|
||||
$queue->enqueue('hey');
|
||||
$queue->enqueue('hi');
|
||||
|
||||
self::assertCount(3, $queue);
|
||||
self::assertSame('hello', $queue->pull());
|
||||
self::assertCount(2, $queue);
|
||||
self::assertSame('hey', $queue->pull());
|
||||
self::assertCount(1, $queue);
|
||||
self::assertSame('hi', $queue->pull());
|
||||
self::assertCount(0, $queue);
|
||||
self::assertNull($queue->pull());
|
||||
}
|
||||
|
||||
public function testPullReturnsNullWhenTheQueueIsEmpty(): void
|
||||
{
|
||||
$queue = new DataStructure\Queue();
|
||||
|
||||
self::assertCount(0, $queue);
|
||||
self::assertNull($queue->pull());
|
||||
}
|
||||
|
||||
public function testDequeueThrowsWhenTheQueueIsEmpty(): void
|
||||
{
|
||||
$queue = new DataStructure\Queue();
|
||||
|
||||
$this->expectException(Psl\Exception\InvariantViolationException::class);
|
||||
$this->expectExceptionMessage('Cannot dequeue a node from an empty Queue.');
|
||||
|
||||
$queue->dequeue();
|
||||
}
|
||||
}
|
73
tests/Psl/DataStructure/StackTest.php
Normal file
73
tests/Psl/DataStructure/StackTest.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Psl\Tests\DataStructure;
|
||||
|
||||
use Psl;
|
||||
use Psl\DataStructure\Stack;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class StackTest extends TestCase
|
||||
{
|
||||
public function testPushAndPop(): void
|
||||
{
|
||||
$stack = new Stack();
|
||||
$stack->push('hello');
|
||||
$stack->push('hey');
|
||||
$stack->push('hi');
|
||||
|
||||
self::assertCount(3, $stack);
|
||||
|
||||
self::assertSame('hi', $stack->peek());
|
||||
|
||||
self::assertSame('hi', $stack->pop());
|
||||
self::assertSame('hey', $stack->pop());
|
||||
self::assertSame('hello', $stack->pop());
|
||||
|
||||
self::assertNull($stack->pull());
|
||||
}
|
||||
|
||||
public function testPeek(): void
|
||||
{
|
||||
$stack = new Stack();
|
||||
|
||||
self::assertNull($stack->peek());
|
||||
|
||||
$stack->push('hello');
|
||||
|
||||
self::assertNotNull($stack->peek());
|
||||
self::assertSame('hello', $stack->peek());
|
||||
}
|
||||
|
||||
public function testPopThrowsForEmptyStack(): void
|
||||
{
|
||||
$stack = new Stack();
|
||||
$stack->push('hello');
|
||||
|
||||
self::assertSame('hello', $stack->pop());
|
||||
|
||||
$this->expectException(Psl\Exception\InvariantViolationException::class);
|
||||
$this->expectExceptionMessage('Cannot pop an item from an empty Stack.');
|
||||
|
||||
$stack->pop();
|
||||
}
|
||||
|
||||
public function testPullReturnsNullForEmptyStack(): void
|
||||
{
|
||||
$stack = new Stack();
|
||||
$stack->push('hello');
|
||||
|
||||
self::assertSame('hello', $stack->pull());
|
||||
self::assertNull($stack->pull());
|
||||
}
|
||||
|
||||
public function testCount(): void
|
||||
{
|
||||
$stack = new Stack();
|
||||
self::assertSame(0, $stack->count());
|
||||
|
||||
$stack->push('hello');
|
||||
self::assertSame(1, $stack->count());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user