Skip to content

Commit 04b2e94

Browse files
committed
chore(tests): remove exercise-only tests; collapse duplicates; extract ClickHouseTestCase
Test cleanup pass on the files added by this PR. Removed: - testDualReadSamplerActivates (events + gauges variants) — these asserted the route log fired after enabling the sampler but never proved the sampler did anything; the divergence / agreement tests cover the actual behaviour. Collapsed via @dataProvider: - testTopNBy{Path,Country,Service,MethodStatus}RoutesToMv → single testTopNGroupedQueryRoutesToMatchingMv with 4 provider entries. - testTopGaugesBy{Service,Resource}RoutesToMv → single testTopGaugesGroupedQueryRoutesToMatchingMv with 2 provider entries. Extracted ClickHouseTestCase base class: - makeAdapter() centralizes the 6 env-var lookup + setNamespace + setSharedTables block duplicated across all six new test files. - databaseName() reads the private `database` property. - resolveTableName() invokes a private accessor returning a table name. - queryRaw() invokes the private query() entry point. The base namespace `Utopia\Tests\Usage\Adapter` reflects the actual on-disk path, so PSR-4 resolves it without a classmap entry. Also dropped a handful of rationale comments and unused `use ReflectionClass` imports made redundant by the helper methods. Net: -484 / +118 in the existing files, +86 in the new base. Total delta -280 test LOC, -2 tests (258 vs 260) while gaining coverage from the dataProvider expansions.
1 parent d9ed227 commit 04b2e94

7 files changed

Lines changed: 204 additions & 484 deletions

tests/Usage/Adapter/ClickHouseDimRollupTest.php

Lines changed: 14 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,8 @@
22

33
namespace Utopia\Tests\Adapter;
44

5-
use PHPUnit\Framework\TestCase;
6-
use ReflectionClass;
75
use Utopia\Query\Query;
6+
use Utopia\Tests\Usage\Adapter\ClickHouseTestCase;
87
use Utopia\Usage\Adapter\ClickHouse as ClickHouseAdapter;
98
use Utopia\Usage\Usage;
109

@@ -13,7 +12,7 @@
1312
* by_service / by_method_status) is created by setup() and that writes to
1413
* the raw events table fan out into each rollup table.
1514
*/
16-
class ClickHouseDimRollupTest extends TestCase
15+
class ClickHouseDimRollupTest extends ClickHouseTestCase
1716
{
1817
private Usage $usage;
1918

@@ -29,21 +28,7 @@ class ClickHouseDimRollupTest extends TestCase
2928

3029
protected function setUp(): void
3130
{
32-
$host = getenv('CLICKHOUSE_HOST') ?: 'clickhouse';
33-
$username = getenv('CLICKHOUSE_USER') ?: 'default';
34-
$password = getenv('CLICKHOUSE_PASSWORD') ?: 'clickhouse';
35-
$port = (int) (getenv('CLICKHOUSE_PORT') ?: 8123);
36-
$secure = (bool) (getenv('CLICKHOUSE_SECURE') ?: false);
37-
38-
$this->adapter = new ClickHouseAdapter($host, $username, $password, $port, $secure);
39-
$this->adapter->setNamespace('utopia_usage_dim_rollup');
40-
$this->adapter->setSharedTables(true);
41-
$this->adapter->setTenant('1');
42-
43-
if ($database = getenv('CLICKHOUSE_DATABASE')) {
44-
$this->adapter->setDatabase($database);
45-
}
46-
31+
$this->adapter = $this->makeAdapter('utopia_usage_dim_rollup');
4732
$this->usage = new Usage($this->adapter);
4833
$this->usage->setup();
4934
$this->usage->purge();
@@ -87,9 +72,6 @@ public function testWritesPropagateToEachRollup(): void
8772
],
8873
], Usage::TYPE_EVENT));
8974

90-
// MVs are synchronous on insert by default in ClickHouse, but the
91-
// SummingMergeTree won't merge identical sort keys until background
92-
// merges run — we count rows, not sum, to check propagation.
9375
foreach ($this->rollups as $rollup) {
9476
$table = $this->getDimRollupTable($rollup['name']);
9577
$count = $this->countRows($table);
@@ -124,9 +106,6 @@ public function testPurgeByIdFiltersDropAllRollupRowsForThatDay(): void
124106
['metric' => $metric, 'value' => 11, 'tags' => ['path' => '/v1/x', 'method' => 'GET', 'status' => '200', 'service' => 'storage', 'country' => 'us']],
125107
], Usage::TYPE_EVENT));
126108

127-
// id only exists on raw events — rollups don't store it. The purge
128-
// helper must NOT attempt `WHERE id = ...` against the rollups; it
129-
// should fall through to whole-day deletion.
130109
$this->usage->purge([
131110
Query::equal('metric', [$metric]),
132111
Query::equal('id', ['nonexistent-id']),
@@ -151,10 +130,6 @@ public function testPurgeByPathClearsAllRollupsForThatDay(): void
151130
['metric' => $metric, 'value' => 7, 'tags' => ['path' => '/v1/x', 'method' => 'GET', 'status' => '200', 'service' => 'storage', 'country' => 'us']],
152131
], Usage::TYPE_EVENT));
153132

154-
// Purge by a column (path) that only the by_path rollup stores.
155-
// Cross-dim rollups (by_country, by_service, by_method_status) cannot
156-
// narrow by path, but they must still drop their stale row for the
157-
// affected day or routed reads will over-report.
158133
$this->usage->purge([
159134
Query::equal('metric', [$metric]),
160135
Query::equal('path', ['/v1/x']),
@@ -173,49 +148,26 @@ public function testPurgeByPathClearsAllRollupsForThatDay(): void
173148

174149
private function getDimRollupTable(string $name): string
175150
{
176-
$reflection = new ReflectionClass($this->adapter);
177-
$method = $reflection->getMethod('getDimRollupTableName');
178-
$method->setAccessible(true);
179-
$raw = $method->invoke($this->adapter, $name);
180-
return is_string($raw) ? $raw : '';
151+
return $this->resolveTableName($this->adapter, 'getDimRollupTableName', [$name]);
181152
}
182153

183154
private function tableExists(string $table): bool
184155
{
185-
$reflection = new ReflectionClass($this->adapter);
186-
$dbProp = $reflection->getProperty('database');
187-
$dbProp->setAccessible(true);
188-
$databaseValue = $dbProp->getValue($this->adapter);
189-
$database = is_string($databaseValue) ? $databaseValue : '';
190-
191-
$sql = "EXISTS TABLE `{$database}`.`{$table}` FORMAT JSON";
192-
$query = $reflection->getMethod('query');
193-
$query->setAccessible(true);
194-
$raw = $query->invoke($this->adapter, $sql, []);
195-
$rawString = is_string($raw) ? $raw : '';
196-
$json = json_decode($rawString, true);
156+
$database = $this->databaseName($this->adapter);
157+
$raw = $this->queryRaw($this->adapter, "EXISTS TABLE `{$database}`.`{$table}` FORMAT JSON");
158+
$json = json_decode($raw, true);
197159
if (is_array($json) && isset($json['data'][0]) && is_array($json['data'][0])) {
198-
$row = $json['data'][0];
199-
$value = $row['result'] ?? 0;
160+
$value = $json['data'][0]['result'] ?? 0;
200161
return ((int) $value) === 1;
201162
}
202163
return false;
203164
}
204165

205166
private function countRows(string $table): int
206167
{
207-
$reflection = new ReflectionClass($this->adapter);
208-
$dbProp = $reflection->getProperty('database');
209-
$dbProp->setAccessible(true);
210-
$databaseValue = $dbProp->getValue($this->adapter);
211-
$database = is_string($databaseValue) ? $databaseValue : '';
212-
213-
$sql = "SELECT count() AS c FROM `{$database}`.`{$table}` FORMAT JSON";
214-
$query = $reflection->getMethod('query');
215-
$query->setAccessible(true);
216-
$raw = $query->invoke($this->adapter, $sql, []);
217-
$rawString = is_string($raw) ? $raw : '';
218-
$json = json_decode($rawString, true);
168+
$database = $this->databaseName($this->adapter);
169+
$raw = $this->queryRaw($this->adapter, "SELECT count() AS c FROM `{$database}`.`{$table}` FORMAT JSON");
170+
$json = json_decode($raw, true);
219171
if (is_array($json) && isset($json['data'][0]) && is_array($json['data'][0])) {
220172
return (int) ($json['data'][0]['c'] ?? 0);
221173
}
@@ -224,19 +176,11 @@ private function countRows(string $table): int
224176

225177
private function sumValue(string $table, string $metric): int
226178
{
227-
$reflection = new ReflectionClass($this->adapter);
228-
$dbProp = $reflection->getProperty('database');
229-
$dbProp->setAccessible(true);
230-
$databaseValue = $dbProp->getValue($this->adapter);
231-
$database = is_string($databaseValue) ? $databaseValue : '';
232-
179+
$database = $this->databaseName($this->adapter);
233180
$sql = "SELECT sum(value) AS s FROM `{$database}`.`{$table}` "
234181
. "WHERE metric = '" . addslashes($metric) . "' FORMAT JSON";
235-
$query = $reflection->getMethod('query');
236-
$query->setAccessible(true);
237-
$raw = $query->invoke($this->adapter, $sql, []);
238-
$rawString = is_string($raw) ? $raw : '';
239-
$json = json_decode($rawString, true);
182+
$raw = $this->queryRaw($this->adapter, $sql);
183+
$json = json_decode($raw, true);
240184
if (is_array($json) && isset($json['data'][0]) && is_array($json['data'][0])) {
241185
return (int) ($json['data'][0]['s'] ?? 0);
242186
}

0 commit comments

Comments
 (0)