Skip to content

Commit a40b76d

Browse files
authored
Extract abstract MultiQueryParserTestCase to remove test duplication (#45)
Move shared test methods (testSuperfluousSemicolons, testEdgeCases, testChunkBoundary, testFile, testFileWithRandomizedChunking, testFileWithAllTwoChunkCombinations, testParseFileThrowsOnNonExistentFile) and the randomChunks helper into an abstract base class. Individual parser tests now contain only data providers and parser-specific overrides. Also move test SQL data files from tests/cases/data/ to tests/data/.
1 parent d5bcb62 commit a40b76d

7 files changed

Lines changed: 246 additions & 338 deletions

tests/cases/MySqlMultiQueryParserTest.phpt

Lines changed: 14 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -6,102 +6,42 @@
66

77
namespace Nextras\MultiQueryParser;
88

9-
use LogicException;
10-
use Nextras\MultiQueryParser\Exception\RuntimeException;
119
use Tester\Assert;
12-
use Tester\TestCase;
1310

1411

1512
require_once __DIR__ . '/../bootstrap.php';
13+
require_once __DIR__ . '/../inc/MultiQueryParserTestCase.php';
1614

1715

18-
class MySqlMultiQueryParserTest extends TestCase
16+
class MySqlMultiQueryParserTest extends MultiQueryParserTestCase
1917
{
20-
/**
21-
* @dataProvider provideSuperfluousSemicolonsData
22-
* @param list<string> $expectedQueries
23-
*/
24-
public function testSuperfluousSemicolons(string $content, array $expectedQueries): void
25-
{
26-
$parser = new MySqlMultiQueryParser();
27-
$queries = iterator_to_array($parser->parseString($content));
28-
Assert::same($expectedQueries, $queries);
29-
}
30-
31-
32-
/**
33-
* @dataProvider provideDelimitersData
34-
* @param list<string> $expectedQueries
35-
*/
36-
public function testDelimiter(string $content, array $expectedQueries): void
18+
protected function createParser(): IMultiQueryParser
3719
{
38-
$parser = new MySqlMultiQueryParser();
39-
$queries = iterator_to_array($parser->parseString($content));
40-
Assert::same($expectedQueries, $queries);
20+
return new MySqlMultiQueryParser();
4121
}
4222

4323

44-
public function testFile(): void
24+
protected function getDataFilePath(): string
4525
{
46-
$parser = new MySqlMultiQueryParser();
47-
$queries = iterator_to_array($parser->parseFile(__DIR__ . '/data/mysql.sql'));
48-
Assert::count(60, $queries);
26+
return __DIR__ . '/../data/mysql.sql';
4927
}
5028

5129

52-
public function testFileWithRandomizedChunking(): void
30+
protected function getExpectedFileQueryCount(): int
5331
{
54-
$content = file_get_contents(__DIR__ . '/data/mysql.sql');
55-
56-
if ($content === false) {
57-
throw new LogicException('Failed to read file content');
58-
}
59-
60-
$parser = new MySqlMultiQueryParser();
61-
$expected = iterator_to_array($parser->parseString($content));
62-
63-
for ($i = 0; $i < 100; $i++) {
64-
$chunks = self::randomChunks($content);
65-
$queries = iterator_to_array($parser->parseStringStream(new \ArrayIterator($chunks)));
66-
Assert::same($expected, $queries, "Failed with chunk sizes: " . implode(', ', array_map('strlen', $chunks)));
67-
}
68-
}
69-
70-
71-
public function testFileWithAllTwoChunkCombinations(): void
72-
{
73-
$content = file_get_contents(__DIR__ . '/data/mysql.sql');
74-
75-
if ($content === false) {
76-
throw new LogicException('Failed to read file content');
77-
}
78-
79-
$parser = new MySqlMultiQueryParser();
80-
$expected = iterator_to_array($parser->parseString($content));
81-
$len = strlen($content);
82-
83-
for ($i = 0; $i <= $len; $i++) {
84-
$chunks = [substr($content, 0, $i), substr($content, $i)];
85-
$queries = iterator_to_array($parser->parseStringStream(new \ArrayIterator($chunks)));
86-
Assert::same($expected, $queries, "Failed with chunk boundary at offset $i");
87-
}
32+
return 60;
8833
}
8934

9035

9136
/**
92-
* @return list<string>
37+
* @dataProvider provideDelimitersData
38+
* @param list<string> $expectedQueries
9339
*/
94-
private static function randomChunks(string $s): array
40+
public function testDelimiter(string $content, array $expectedQueries): void
9541
{
96-
$chunks = [];
97-
$offset = 0;
98-
$len = strlen($s);
99-
while ($offset < $len) {
100-
$size = random_int(1, max(1, min(256, $len - $offset)));
101-
$chunks[] = substr($s, $offset, $size);
102-
$offset += $size;
103-
}
104-
return $chunks;
42+
$parser = $this->createParser();
43+
$queries = iterator_to_array($parser->parseString($content));
44+
Assert::same($expectedQueries, $queries);
10545
}
10646

10747

@@ -212,27 +152,6 @@ class MySqlMultiQueryParserTest extends TestCase
212152
}
213153

214154

215-
/**
216-
* @dataProvider provideEdgeCasesData
217-
* @param list<string> $expectedQueries
218-
*/
219-
public function testEdgeCases(string $content, array $expectedQueries): void
220-
{
221-
$parser = new MySqlMultiQueryParser();
222-
$queries = iterator_to_array($parser->parseString($content));
223-
Assert::same($expectedQueries, $queries);
224-
}
225-
226-
227-
public function testParseFileThrowsOnNonExistentFile(): void
228-
{
229-
$parser = new MySqlMultiQueryParser();
230-
Assert::exception(function () use ($parser) {
231-
$parser->parseFile(__DIR__ . '/data/nonexistent.sql');
232-
}, RuntimeException::class);
233-
}
234-
235-
236155
/**
237156
* @return list<array{string, list<string>}>
238157
*/
@@ -327,19 +246,6 @@ class MySqlMultiQueryParserTest extends TestCase
327246
}
328247

329248

330-
/**
331-
* @dataProvider provideChunkBoundaryData
332-
* @param list<string> $chunks
333-
* @param list<string> $expectedQueries
334-
*/
335-
public function testChunkBoundary(array $chunks, array $expectedQueries): void
336-
{
337-
$parser = new MySqlMultiQueryParser();
338-
$queries = iterator_to_array($parser->parseStringStream(new \ArrayIterator($chunks)));
339-
Assert::same($expectedQueries, $queries);
340-
}
341-
342-
343249
/**
344250
* @return list<array{list<string>, list<string>}>
345251
*/

tests/cases/PostgreSqlMultiQueryParserTest.phpt

Lines changed: 32 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,46 @@
66

77
namespace Nextras\MultiQueryParser;
88

9-
use LogicException;
109
use Tester\Assert;
11-
use Tester\TestCase;
1210

1311

1412
require_once __DIR__ . '/../bootstrap.php';
13+
require_once __DIR__ . '/../inc/MultiQueryParserTestCase.php';
1514

1615

17-
class PostgreSqlMultiQueryParserTest extends TestCase
16+
class PostgreSqlMultiQueryParserTest extends MultiQueryParserTestCase
1817
{
19-
/**
20-
* @dataProvider provideSuperfluousSemicolonsData
21-
* @param list<string> $expectedQueries
22-
*/
23-
public function testSuperfluousSemicolons(string $content, array $expectedQueries): void
18+
protected function createParser(): IMultiQueryParser
2419
{
25-
$parser = new PostgreSqlMultiQueryParser();
26-
$queries = iterator_to_array($parser->parseString($content));
27-
Assert::same($expectedQueries, $queries);
20+
return new PostgreSqlMultiQueryParser();
21+
}
22+
23+
24+
protected function getDataFilePath(): string
25+
{
26+
return __DIR__ . '/../data/postgres.sql';
27+
}
28+
29+
30+
protected function getExpectedFileQueryCount(): int
31+
{
32+
return 67;
33+
}
34+
35+
36+
public function testFile(): void
37+
{
38+
$parser = $this->createParser();
39+
$queries = iterator_to_array($parser->parseFile($this->getDataFilePath()));
40+
Assert::count($this->getExpectedFileQueryCount(), $queries);
41+
Assert::same("CREATE FUNCTION \"book_collections_before\"() RETURNS TRIGGER AS
42+
\$BODY$
43+
BEGIN
44+
NEW.\"updated_at\" = NOW();
45+
return NEW;
46+
END;
47+
\$BODY$
48+
LANGUAGE 'plpgsql' VOLATILE", $queries[16]);
2849
}
2950

3051

@@ -62,18 +83,6 @@ class PostgreSqlMultiQueryParserTest extends TestCase
6283
}
6384

6485

65-
/**
66-
* @dataProvider provideEdgeCasesData
67-
* @param list<string> $expectedQueries
68-
*/
69-
public function testEdgeCases(string $content, array $expectedQueries): void
70-
{
71-
$parser = new PostgreSqlMultiQueryParser();
72-
$queries = iterator_to_array($parser->parseString($content));
73-
Assert::same($expectedQueries, $queries);
74-
}
75-
76-
7786
/**
7887
* @return list<array{string, list<string>}>
7988
*/
@@ -157,19 +166,6 @@ class PostgreSqlMultiQueryParserTest extends TestCase
157166
}
158167

159168

160-
/**
161-
* @dataProvider provideChunkBoundaryData
162-
* @param list<string> $chunks
163-
* @param list<string> $expectedQueries
164-
*/
165-
public function testChunkBoundary(array $chunks, array $expectedQueries): void
166-
{
167-
$parser = new PostgreSqlMultiQueryParser();
168-
$queries = iterator_to_array($parser->parseStringStream(new \ArrayIterator($chunks)));
169-
Assert::same($expectedQueries, $queries);
170-
}
171-
172-
173169
/**
174170
* @return list<array{list<string>, list<string>}>
175171
*/
@@ -213,78 +209,6 @@ class PostgreSqlMultiQueryParserTest extends TestCase
213209
],
214210
];
215211
}
216-
217-
218-
public function testFile(): void
219-
{
220-
$parser = new PostgreSqlMultiQueryParser();
221-
$queries = iterator_to_array($parser->parseFile(__DIR__ . '/data/postgres.sql'));
222-
Assert::count(67, $queries);
223-
Assert::same("CREATE FUNCTION \"book_collections_before\"() RETURNS TRIGGER AS
224-
\$BODY$
225-
BEGIN
226-
NEW.\"updated_at\" = NOW();
227-
return NEW;
228-
END;
229-
\$BODY$
230-
LANGUAGE 'plpgsql' VOLATILE", $queries[16]);
231-
}
232-
233-
234-
public function testFileWithRandomizedChunking(): void
235-
{
236-
$content = file_get_contents(__DIR__ . '/data/postgres.sql');
237-
238-
if ($content === false) {
239-
throw new LogicException('Failed to read file content');
240-
}
241-
242-
$parser = new PostgreSqlMultiQueryParser();
243-
$expected = iterator_to_array($parser->parseString($content));
244-
245-
for ($i = 0; $i < 100; $i++) {
246-
$chunks = self::randomChunks($content);
247-
$queries = iterator_to_array($parser->parseStringStream(new \ArrayIterator($chunks)));
248-
Assert::same($expected, $queries, "Failed with chunk sizes: " . implode(', ', array_map('strlen', $chunks)));
249-
}
250-
}
251-
252-
253-
public function testFileWithAllTwoChunkCombinations(): void
254-
{
255-
$content = file_get_contents(__DIR__ . '/data/postgres.sql');
256-
257-
if ($content === false) {
258-
throw new LogicException('Failed to read file content');
259-
}
260-
261-
$parser = new PostgreSqlMultiQueryParser();
262-
$expected = iterator_to_array($parser->parseString($content));
263-
$len = strlen($content);
264-
265-
for ($i = 0; $i <= $len; $i++) {
266-
$chunks = [substr($content, 0, $i), substr($content, $i)];
267-
$queries = iterator_to_array($parser->parseStringStream(new \ArrayIterator($chunks)));
268-
Assert::same($expected, $queries, "Failed with chunk boundary at offset $i");
269-
}
270-
}
271-
272-
273-
/**
274-
* @return list<string>
275-
*/
276-
private static function randomChunks(string $s): array
277-
{
278-
$chunks = [];
279-
$offset = 0;
280-
$len = strlen($s);
281-
while ($offset < $len) {
282-
$size = random_int(1, max(1, min(256, $len - $offset)));
283-
$chunks[] = substr($s, $offset, $size);
284-
$offset += $size;
285-
}
286-
return $chunks;
287-
}
288212
}
289213

290214

0 commit comments

Comments
 (0)