Skip to content

Commit aceca21

Browse files
author
nejc
committed
Add TypeSafeArray implementation with type constraints and update scalar types
1 parent 20fc451 commit aceca21

File tree

7 files changed

+606
-16
lines changed

7 files changed

+606
-16
lines changed
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
3+
namespace Tests\Composite\Arrays;
4+
5+
use Nejcc\PhpDatatypes\Composite\Arrays\TypeSafeArray;
6+
use Nejcc\PhpDatatypes\Exceptions\InvalidArgumentException;
7+
use Nejcc\PhpDatatypes\Exceptions\TypeMismatchException;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class TypeSafeArrayTest extends TestCase
11+
{
12+
public function testCreateValidTypeSafeArray(): void
13+
{
14+
$array = new TypeSafeArray(\stdClass::class);
15+
$this->assertInstanceOf(TypeSafeArray::class, $array);
16+
$this->assertEquals(\stdClass::class, $array->getElementType());
17+
}
18+
19+
public function testCreateWithInvalidType(): void
20+
{
21+
$this->expectException(InvalidArgumentException::class);
22+
new TypeSafeArray('NonExistentClass');
23+
}
24+
25+
public function testAddValidElement(): void
26+
{
27+
$array = new TypeSafeArray(\stdClass::class);
28+
$obj = new \stdClass();
29+
$array[] = $obj;
30+
$this->assertCount(1, $array);
31+
$this->assertSame($obj, $array[0]);
32+
}
33+
34+
public function testAddInvalidElement(): void
35+
{
36+
$array = new TypeSafeArray(\stdClass::class);
37+
$this->expectException(TypeMismatchException::class);
38+
$array[] = 'not an object';
39+
}
40+
41+
public function testInitializeWithValidData(): void
42+
{
43+
$data = [new \stdClass(), new \stdClass()];
44+
$array = new TypeSafeArray(\stdClass::class, $data);
45+
$this->assertCount(2, $array);
46+
}
47+
48+
public function testInitializeWithInvalidData(): void
49+
{
50+
$data = [new \stdClass(), 'not an object'];
51+
$this->expectException(TypeMismatchException::class);
52+
new TypeSafeArray(\stdClass::class, $data);
53+
}
54+
55+
public function testMapOperation(): void
56+
{
57+
$array = new TypeSafeArray(\stdClass::class);
58+
$obj1 = new \stdClass();
59+
$obj2 = new \stdClass();
60+
$array[] = $obj1;
61+
$array[] = $obj2;
62+
63+
$mapped = $array->map(function($item) {
64+
$new = new \stdClass();
65+
$new->mapped = true;
66+
return $new;
67+
});
68+
69+
$this->assertInstanceOf(TypeSafeArray::class, $mapped);
70+
$this->assertCount(2, $mapped);
71+
$this->assertTrue($mapped[0]->mapped);
72+
$this->assertTrue($mapped[1]->mapped);
73+
}
74+
75+
public function testFilterOperation(): void
76+
{
77+
$array = new TypeSafeArray(\stdClass::class);
78+
$obj1 = new \stdClass();
79+
$obj1->value = 1;
80+
$obj2 = new \stdClass();
81+
$obj2->value = 2;
82+
$array[] = $obj1;
83+
$array[] = $obj2;
84+
85+
$filtered = $array->filter(function($item) {
86+
return $item->value === 1;
87+
});
88+
89+
$this->assertInstanceOf(TypeSafeArray::class, $filtered);
90+
$this->assertCount(1, $filtered);
91+
$this->assertEquals(1, $filtered[0]->value);
92+
}
93+
94+
public function testReduceOperation(): void
95+
{
96+
$array = new TypeSafeArray(\stdClass::class);
97+
$obj1 = new \stdClass();
98+
$obj1->value = 1;
99+
$obj2 = new \stdClass();
100+
$obj2->value = 2;
101+
$array[] = $obj1;
102+
$array[] = $obj2;
103+
104+
$sum = $array->reduce(function($carry, $item) {
105+
return $carry + $item->value;
106+
}, 0);
107+
108+
$this->assertEquals(3, $sum);
109+
}
110+
111+
public function testArrayAccess(): void
112+
{
113+
$array = new TypeSafeArray(\stdClass::class);
114+
$obj = new \stdClass();
115+
116+
// Test offsetSet
117+
$array[0] = $obj;
118+
$this->assertTrue(isset($array[0]));
119+
$this->assertSame($obj, $array[0]);
120+
121+
// Test offsetUnset
122+
unset($array[0]);
123+
$this->assertFalse(isset($array[0]));
124+
}
125+
126+
public function testIterator(): void
127+
{
128+
$array = new TypeSafeArray(\stdClass::class);
129+
$obj1 = new \stdClass();
130+
$obj2 = new \stdClass();
131+
$array[] = $obj1;
132+
$array[] = $obj2;
133+
134+
$items = [];
135+
foreach ($array as $item) {
136+
$items[] = $item;
137+
}
138+
139+
$this->assertCount(2, $items);
140+
$this->assertSame($obj1, $items[0]);
141+
$this->assertSame($obj2, $items[1]);
142+
}
143+
144+
public function testToString(): void
145+
{
146+
$array = new TypeSafeArray(\stdClass::class);
147+
$obj = new \stdClass();
148+
$obj->test = 'value';
149+
$array[] = $obj;
150+
151+
$this->assertEquals('[{"test":"value"}]', (string)$array);
152+
}
153+
}

Tests/Composite/Vector/Vec2Test.php

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
<?php
2+
3+
namespace Tests\Composite\Vector;
4+
5+
use Nejcc\PhpDatatypes\Composite\Vector\Vec2;
6+
use Nejcc\PhpDatatypes\Exceptions\InvalidArgumentException;
7+
use PHPUnit\Framework\TestCase;
8+
9+
class Vec2Test extends TestCase
10+
{
11+
public function testCreateValidVec2(): void
12+
{
13+
$vec = new Vec2([1.0, 2.0]);
14+
$this->assertEquals(1.0, $vec->getX());
15+
$this->assertEquals(2.0, $vec->getY());
16+
}
17+
18+
public function testCreateInvalidComponentCount(): void
19+
{
20+
$this->expectException(InvalidArgumentException::class);
21+
new Vec2([1.0]);
22+
}
23+
24+
public function testCreateWithNonNumericComponents(): void
25+
{
26+
$this->expectException(InvalidArgumentException::class);
27+
new Vec2(['a', 'b']);
28+
}
29+
30+
public function testMagnitude(): void
31+
{
32+
$vec = new Vec2([3.0, 4.0]);
33+
$this->assertEquals(5.0, $vec->magnitude());
34+
}
35+
36+
public function testNormalize(): void
37+
{
38+
$vec = new Vec2([3.0, 4.0]);
39+
$normalized = $vec->normalize();
40+
$this->assertEquals(1.0, $normalized->magnitude());
41+
$this->assertEquals(0.6, $normalized->getX());
42+
$this->assertEquals(0.8, $normalized->getY());
43+
}
44+
45+
public function testNormalizeZeroVector(): void
46+
{
47+
$vec = new Vec2([0.0, 0.0]);
48+
$this->expectException(InvalidArgumentException::class);
49+
$vec->normalize();
50+
}
51+
52+
public function testDotProduct(): void
53+
{
54+
$vec1 = new Vec2([1.0, 2.0]);
55+
$vec2 = new Vec2([3.0, 4.0]);
56+
$this->assertEquals(11.0, $vec1->dot($vec2));
57+
}
58+
59+
public function testAdd(): void
60+
{
61+
$vec1 = new Vec2([1.0, 2.0]);
62+
$vec2 = new Vec2([3.0, 4.0]);
63+
$result = $vec1->add($vec2);
64+
$this->assertEquals(4.0, $result->getX());
65+
$this->assertEquals(6.0, $result->getY());
66+
}
67+
68+
public function testSubtract(): void
69+
{
70+
$vec1 = new Vec2([3.0, 4.0]);
71+
$vec2 = new Vec2([1.0, 2.0]);
72+
$result = $vec1->subtract($vec2);
73+
$this->assertEquals(2.0, $result->getX());
74+
$this->assertEquals(2.0, $result->getY());
75+
}
76+
77+
public function testScale(): void
78+
{
79+
$vec = new Vec2([1.0, 2.0]);
80+
$result = $vec->scale(2.0);
81+
$this->assertEquals(2.0, $result->getX());
82+
$this->assertEquals(4.0, $result->getY());
83+
}
84+
85+
public function testCross(): void
86+
{
87+
$vec1 = new Vec2([1.0, 2.0]);
88+
$vec2 = new Vec2([3.0, 4.0]);
89+
$this->assertEquals(-2.0, $vec1->cross($vec2));
90+
}
91+
92+
public function testZero(): void
93+
{
94+
$vec = Vec2::zero();
95+
$this->assertEquals(0.0, $vec->getX());
96+
$this->assertEquals(0.0, $vec->getY());
97+
}
98+
99+
public function testUnitX(): void
100+
{
101+
$vec = Vec2::unitX();
102+
$this->assertEquals(1.0, $vec->getX());
103+
$this->assertEquals(0.0, $vec->getY());
104+
}
105+
106+
public function testUnitY(): void
107+
{
108+
$vec = Vec2::unitY();
109+
$this->assertEquals(0.0, $vec->getX());
110+
$this->assertEquals(1.0, $vec->getY());
111+
}
112+
113+
public function testToString(): void
114+
{
115+
$vec = new Vec2([1.0, 2.0]);
116+
$this->assertEquals('(1, 2)', (string)$vec);
117+
}
118+
119+
public function testEquals(): void
120+
{
121+
$vec1 = new Vec2([1.0, 2.0]);
122+
$vec2 = new Vec2([1.0, 2.0]);
123+
$vec3 = new Vec2([2.0, 1.0]);
124+
125+
$this->assertTrue($vec1->equals($vec2));
126+
$this->assertFalse($vec1->equals($vec3));
127+
}
128+
129+
public function testDistance(): void
130+
{
131+
$vec1 = new Vec2([0.0, 0.0]);
132+
$vec2 = new Vec2([3.0, 4.0]);
133+
$this->assertEquals(5.0, $vec1->distance($vec2));
134+
}
135+
}

0 commit comments

Comments
 (0)