d3ro-voice/server/supabase/tests/mobile-reward-race.integration.ps1
2026-08-29 18:33:45 +09:00

89 lines
3.1 KiB
PowerShell

param(
[string]$DatabaseContainer = 'supabase_db_d3ro-voice'
)
$ErrorActionPreference = 'Stop'
$userId = '20000000-0000-4000-8000-000000000099'
$runId = [guid]::NewGuid().ToString('N')
$firstTransactionId = "race-transaction-first-$runId"
$secondTransactionId = "race-transaction-second-$runId"
function Invoke-D3roSql {
param([Parameter(Mandatory)][string]$Sql)
$output = $Sql | docker exec -i $DatabaseContainer psql -v ON_ERROR_STOP=1 -U postgres -d postgres -t -A
if ($LASTEXITCODE -ne 0) { throw 'D3RO PostgreSQL command failed' }
return ($output -join "`n").Trim()
}
$setup = @"
DELETE FROM auth.users WHERE id = '$userId';
INSERT INTO auth.users (
id, aud, role, email, encrypted_password, email_confirmed_at,
raw_app_meta_data, raw_user_meta_data, created_at, updated_at
) VALUES (
'$userId', 'authenticated', 'authenticated',
'reward-race@example.invalid', crypt('fixture-password', gen_salt('bf')), now(),
'{"provider":"email","providers":["email"]}'::jsonb, '{}'::jsonb, now(), now()
);
UPDATE public.subscriptions
SET tier = 'free', status = 'active', overage_credits = 0
WHERE user_id = '$userId';
"@
try {
[void](Invoke-D3roSql -Sql $setup)
$firstSql = @"
BEGIN;
SELECT public.grant_verified_ad_reward(
'$userId', 'admob:race', 'rewarded_video_quota', '5224354917',
'$firstTransactionId', 50
);
SELECT pg_sleep(2);
COMMIT;
"@
$secondSql = @"
SELECT public.grant_verified_ad_reward(
'$userId', 'admob:race', 'rewarded_video_quota', '5224354917',
'$secondTransactionId', 50
);
"@
$first = Start-Job -ScriptBlock {
param($Container, $Sql)
$Sql | docker exec -i $Container psql -v ON_ERROR_STOP=1 -U postgres -d postgres -t -A
if ($LASTEXITCODE -ne 0) { throw 'first reward connection failed' }
} -ArgumentList $DatabaseContainer, $firstSql
Start-Sleep -Milliseconds 200
$second = Start-Job -ScriptBlock {
param($Container, $Sql)
$Sql | docker exec -i $Container psql -v ON_ERROR_STOP=1 -U postgres -d postgres -t -A
if ($LASTEXITCODE -ne 0) { throw 'second reward connection failed' }
} -ArgumentList $DatabaseContainer, $secondSql
$firstOutput = (Receive-Job -Job $first -Wait -AutoRemoveJob | Out-String)
$secondOutput = (Receive-Job -Job $second -Wait -AutoRemoveJob | Out-String)
if ($firstOutput -notmatch '"granted": true') {
throw "first callback was not granted: $firstOutput"
}
if ($secondOutput -notmatch '"reason": "cooldown"') {
throw "second callback was not serialized into cooldown: $secondOutput"
}
$verification = Invoke-D3roSql -Sql @"
SELECT
(SELECT count(*) FROM public.ad_reward_claims WHERE user_id = '$userId')::text
|| ':' ||
(SELECT overage_credits FROM public.subscriptions WHERE user_id = '$userId')::text;
"@
if ($verification -ne '1:50') {
throw "reward race changed more than one claim/balance: $verification"
}
Write-Output 'mobile_reward_race_ok claims=1 credits=50 second=cooldown'
} finally {
[void](Invoke-D3roSql -Sql @"
DELETE FROM public.ad_reward_receipts
WHERE transaction_id IN ('$firstTransactionId', '$secondTransactionId');
DELETE FROM auth.users WHERE id = '$userId';
"@)
}