Skip to content

Commit 500df06

Browse files
committed
[Store] Add comprehensive unit tests for ChunkDelayTransformer
1 parent 4bb633d commit 500df06

File tree

1 file changed

+261
-0
lines changed

1 file changed

+261
-0
lines changed
Lines changed: 261 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,261 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\AI\Store\Tests\Document\Transformer;
13+
14+
use PHPUnit\Framework\Attributes\CoversClass;
15+
use PHPUnit\Framework\TestCase;
16+
use Symfony\AI\Store\Document\TextDocument;
17+
use Symfony\AI\Store\Document\Transformer\ChunkDelayTransformer;
18+
use Symfony\Component\Clock\ClockInterface;
19+
use Symfony\Component\Clock\MockClock;
20+
use Symfony\Component\Uid\Uuid;
21+
22+
#[CoversClass(ChunkDelayTransformer::class)]
23+
final class ChunkDelayTransformerTest extends TestCase
24+
{
25+
public function testDefaultChunkSizeAndDelay()
26+
{
27+
$clock = $this->createMock(ClockInterface::class);
28+
$clock->expects($this->never())
29+
->method('sleep');
30+
31+
$transformer = new ChunkDelayTransformer($clock);
32+
33+
$documents = [];
34+
for ($i = 0; $i < 30; ++$i) {
35+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
36+
}
37+
38+
$result = iterator_to_array($transformer($documents));
39+
40+
$this->assertCount(30, $result);
41+
for ($i = 0; $i < 30; ++$i) {
42+
$this->assertSame('content-'.$i, $result[$i]->content);
43+
}
44+
}
45+
46+
public function testSleepsAfterChunkSize()
47+
{
48+
$clock = $this->createMock(ClockInterface::class);
49+
$clock->expects($this->once())
50+
->method('sleep')
51+
->with(5);
52+
53+
$transformer = new ChunkDelayTransformer($clock);
54+
55+
$documents = [];
56+
for ($i = 0; $i < 100; ++$i) {
57+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
58+
}
59+
60+
$result = iterator_to_array($transformer($documents, [
61+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 50,
62+
ChunkDelayTransformer::OPTION_DELAY => 5,
63+
]));
64+
65+
$this->assertCount(100, $result);
66+
}
67+
68+
public function testCustomChunkSizeAndDelay()
69+
{
70+
$clock = $this->createMock(ClockInterface::class);
71+
$clock->expects($this->once())
72+
->method('sleep')
73+
->with(2);
74+
75+
$transformer = new ChunkDelayTransformer($clock);
76+
77+
$documents = [];
78+
for ($i = 0; $i < 40; ++$i) {
79+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
80+
}
81+
82+
$result = iterator_to_array($transformer($documents, [
83+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 10,
84+
ChunkDelayTransformer::OPTION_DELAY => 2,
85+
]));
86+
87+
$this->assertCount(40, $result);
88+
}
89+
90+
public function testNoSleepWhenDelayIsZero()
91+
{
92+
$clock = $this->createMock(ClockInterface::class);
93+
$clock->expects($this->never())
94+
->method('sleep');
95+
96+
$transformer = new ChunkDelayTransformer($clock);
97+
98+
$documents = [];
99+
for ($i = 0; $i < 20; ++$i) {
100+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
101+
}
102+
103+
$result = iterator_to_array($transformer($documents, [
104+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 5,
105+
ChunkDelayTransformer::OPTION_DELAY => 0,
106+
]));
107+
108+
$this->assertCount(20, $result);
109+
}
110+
111+
public function testYieldsDocumentsInCorrectOrder()
112+
{
113+
$clock = $this->createMock(ClockInterface::class);
114+
$transformer = new ChunkDelayTransformer($clock);
115+
116+
$documents = [
117+
new TextDocument(Uuid::v4(), 'first'),
118+
new TextDocument(Uuid::v4(), 'second'),
119+
new TextDocument(Uuid::v4(), 'third'),
120+
];
121+
122+
$result = iterator_to_array($transformer($documents, [
123+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 2,
124+
ChunkDelayTransformer::OPTION_DELAY => 1,
125+
]));
126+
127+
$this->assertSame('first', $result[0]->content);
128+
$this->assertSame('second', $result[1]->content);
129+
$this->assertSame('third', $result[2]->content);
130+
}
131+
132+
public function testHandlesEmptyIterable()
133+
{
134+
$clock = $this->createMock(ClockInterface::class);
135+
$clock->expects($this->never())
136+
->method('sleep');
137+
138+
$transformer = new ChunkDelayTransformer($clock);
139+
140+
$result = iterator_to_array($transformer([]));
141+
142+
$this->assertCount(0, $result);
143+
}
144+
145+
public function testSingleDocument()
146+
{
147+
$clock = $this->createMock(ClockInterface::class);
148+
$clock->expects($this->once())
149+
->method('sleep')
150+
->with(5);
151+
152+
$transformer = new ChunkDelayTransformer($clock);
153+
154+
$documents = [new TextDocument(Uuid::v4(), 'single')];
155+
156+
$result = iterator_to_array($transformer($documents, [
157+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 1,
158+
ChunkDelayTransformer::OPTION_DELAY => 5,
159+
]));
160+
161+
$this->assertCount(1, $result);
162+
$this->assertSame('single', $result[0]->content);
163+
}
164+
165+
public function testExactlyChunkSizeDocuments()
166+
{
167+
$clock = $this->createMock(ClockInterface::class);
168+
$clock->expects($this->once())
169+
->method('sleep')
170+
->with(3);
171+
172+
$transformer = new ChunkDelayTransformer($clock);
173+
174+
$documents = [];
175+
for ($i = 0; $i < 10; ++$i) {
176+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
177+
}
178+
179+
$result = iterator_to_array($transformer($documents, [
180+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 10,
181+
ChunkDelayTransformer::OPTION_DELAY => 3,
182+
]));
183+
184+
$this->assertCount(10, $result);
185+
}
186+
187+
public function testMultipleExactChunks()
188+
{
189+
$clock = $this->createMock(ClockInterface::class);
190+
$clock->expects($this->once())
191+
->method('sleep')
192+
->with(1);
193+
194+
$transformer = new ChunkDelayTransformer($clock);
195+
196+
$documents = [];
197+
for ($i = 0; $i < 15; ++$i) {
198+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
199+
}
200+
201+
$result = iterator_to_array($transformer($documents, [
202+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 5,
203+
ChunkDelayTransformer::OPTION_DELAY => 1,
204+
]));
205+
206+
$this->assertCount(15, $result);
207+
}
208+
209+
public function testLazyEvaluation()
210+
{
211+
$clock = $this->createMock(ClockInterface::class);
212+
$clock->expects($this->once())
213+
->method('sleep')
214+
->with(1);
215+
216+
$transformer = new ChunkDelayTransformer($clock);
217+
218+
$documents = [];
219+
for ($i = 0; $i < 10; ++$i) {
220+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
221+
}
222+
223+
$generator = $transformer($documents, [
224+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 3,
225+
ChunkDelayTransformer::OPTION_DELAY => 1,
226+
]);
227+
228+
$count = 0;
229+
foreach ($generator as $document) {
230+
++$count;
231+
if (5 === $count) {
232+
break;
233+
}
234+
}
235+
236+
$this->assertSame(5, $count);
237+
}
238+
239+
public function testWithMockClock()
240+
{
241+
$clock = new MockClock();
242+
$transformer = new ChunkDelayTransformer($clock);
243+
244+
$documents = [];
245+
for ($i = 0; $i < 10; ++$i) {
246+
$documents[] = new TextDocument(Uuid::v4(), 'content-'.$i);
247+
}
248+
249+
$startTime = $clock->now();
250+
251+
iterator_to_array($transformer($documents, [
252+
ChunkDelayTransformer::OPTION_CHUNK_SIZE => 5,
253+
ChunkDelayTransformer::OPTION_DELAY => 30,
254+
]));
255+
256+
$endTime = $clock->now();
257+
$elapsed = $endTime->getTimestamp() - $startTime->getTimestamp();
258+
259+
$this->assertSame(30, $elapsed);
260+
}
261+
}

0 commit comments

Comments
 (0)