Files
Oxicloud/tests/load/scenarios/smoke.js
T
Edouard Vanbelle 0ef4c624c5 chore(load): start implementation of load tests
initial test from Ed's nuc:

    metric                                          pctl  baseline    current     delta    status
    -----------------------------------------------------------------------------------------------
    folder_cascade.list_depth1                      p50   0.3ms       0.3ms       -6.3%    ok
    folder_cascade.list_depth1                      p95   2.3ms       0.5ms       -75.7%   ok
    folder_cascade.list_depth1                      p99   4.7ms       2.5ms       -48.1%   ok
    folder_cascade.list_depth4                      p50   0.4ms       0.3ms       -10.0%   ok
    folder_cascade.list_depth4                      p95   0.9ms       0.6ms       -31.2%   ok
    folder_cascade.list_depth4                      p99   2.4ms       1.0ms       -56.7%   ok
    folder_cascade.list_depth8                      p50   0.3ms       0.3ms       -8.8%    ok
    folder_cascade.list_depth8                      p95   0.6ms       0.5ms       -22.2%   ok
    folder_cascade.list_depth8                      p99   1.9ms       0.5ms       -71.5%   ok
    folder_cascade.list_depth_deep                  p50   0.3ms       0.3ms       -5.0%    ok
    folder_cascade.list_depth_deep                  p95   0.6ms       0.5ms       -18.6%   ok
    folder_cascade.list_depth_deep                  p99   2.0ms       0.7ms       -67.2%   ok
    share_cascade_rebac.list_grants                 p50   0.4ms       0.3ms       -27.6%   ok
    share_cascade_rebac.list_grants                 p95   1.2ms       0.5ms       -57.0%   ok
    share_cascade_rebac.list_grants                 p99   1.7ms       1.1ms       -36.7%   ok
    share_cascade_rebac.fetch_as_grantee_depth1     p50   0.5ms       0.5ms       -11.1%   ok
    share_cascade_rebac.fetch_as_grantee_depth1     p95   1.1ms       0.7ms       -41.2%   ok
    share_cascade_rebac.fetch_as_grantee_depth1     p99   3.0ms       1.3ms       -58.3%   ok
    share_cascade_rebac.fetch_as_grantee_depth4     p50   0.5ms       0.5ms       -13.7%   ok
    share_cascade_rebac.fetch_as_grantee_depth4     p95   1.4ms       0.7ms       -50.5%   ok
    share_cascade_rebac.fetch_as_grantee_depth4     p99   2.2ms       1.1ms       -49.3%   ok
    share_cascade_rebac.fetch_as_grantee_depth8     p50   0.5ms       0.4ms       -16.0%   ok
    share_cascade_rebac.fetch_as_grantee_depth8     p95   0.9ms       0.7ms       -26.1%   ok
    share_cascade_rebac.fetch_as_grantee_depth8     p99   1.5ms       0.9ms       -40.1%   ok
    share_cascade_rebac.fetch_as_grantee_depth_deep p50   0.5ms       0.4ms       -17.3%   ok
    share_cascade_rebac.fetch_as_grantee_depth_deep p95   1.0ms       0.7ms       -31.2%   ok
    share_cascade_rebac.fetch_as_grantee_depth_deep p99   1.6ms       0.8ms       -49.4%   ok
    subject_group_nested.fetch_as_member_depth1     p50   0.5ms       0.4ms       -8.4%    ok
    subject_group_nested.fetch_as_member_depth1     p95   0.6ms       0.6ms       -10.2%   ok
    subject_group_nested.fetch_as_member_depth1     p99   1.4ms       0.6ms       -55.2%   ok
    subject_group_nested.fetch_as_member_depth4     p50   0.5ms       0.5ms       -7.9%    ok
    subject_group_nested.fetch_as_member_depth4     p95   0.6ms       0.6ms       -4.0%    ok
    subject_group_nested.fetch_as_member_depth4     p99   0.7ms       0.6ms       -2.2%    ok
    subject_group_nested.fetch_as_member_depth8     p50   0.5ms       0.4ms       -8.9%    ok
    subject_group_nested.fetch_as_member_depth8     p95   0.5ms       0.6ms       +7.1%    ok
    subject_group_nested.fetch_as_member_depth8     p99   0.6ms       0.7ms       +10.3%   ok
    subject_group_nested.fetch_as_member_depth_deep p50   0.5ms       0.4ms       -7.6%    ok
    subject_group_nested.fetch_as_member_depth_deep p95   0.6ms       0.5ms       -11.9%   ok
    subject_group_nested.fetch_as_member_depth_deep p99   0.6ms       0.7ms       +8.9%    ok
2026-06-18 09:38:25 +02:00

65 lines
2.2 KiB
JavaScript

// smoke.js — fast PR-tier check. Verifies the load harness still builds and
// the server boots, exercising one happy-path of every HTTP verb the long
// scenarios use. No regression gate; run.sh's `smoke.sh` skips compare.mjs.
import { check, sleep } from 'k6';
import http from 'k6/http';
import { BASE, jsonParams, authParams } from '../lib/http.js';
import { login } from '../lib/auth.js';
import { thresholdsFromBaseline } from '../lib/metrics.js';
export const options = {
vus: 1,
iterations: 1,
thresholds: thresholdsFromBaseline('smoke'),
};
// Admin creds match tests/load/test.env defaults — overridable via env.
const USERNAME = __ENV.K6_USERNAME || 'admin';
const PASSWORD = __ENV.K6_PASSWORD || 'TestPassword1!';
export default function () {
// 1. login
const token = login(USERNAME, PASSWORD, 'smoke.login');
// 2. create a scratch folder at root
const folderName = `smoke_${Date.now()}`;
const createRes = http.post(
`${BASE}/api/folders`,
JSON.stringify({ name: folderName }),
jsonParams(token, 'smoke.create_folder'),
);
check(createRes, { 'create folder 200/201': (r) => r.status === 200 || r.status === 201 });
const folderId = createRes.json('id');
// 3. upload a tiny file via multipart
const fileData = http.file('hello\n', 'smoke.txt', 'text/plain');
const uploadRes = http.post(
`${BASE}/api/files/upload`,
{ folder_id: folderId, file: fileData },
{ headers: { Authorization: `Bearer ${token}` }, tags: { op: 'smoke.upload_tiny' } },
);
const uploadOk = check(uploadRes, {
'upload 200/201': (r) => r.status === 200 || r.status === 201,
});
if (!uploadOk) {
console.error(
`upload failed: status=${uploadRes.status}, body=${uploadRes.body}, headers=${JSON.stringify(uploadRes.headers)}`,
);
}
// 4. list root folders for this user
const listRes = http.get(`${BASE}/api/folders`, authParams(token, 'smoke.list_root'));
check(listRes, { 'list root 200': (r) => r.status === 200 });
// 5. delete the scratch folder
const delRes = http.del(
`${BASE}/api/folders/${folderId}`,
null,
authParams(token, 'smoke.delete_folder'),
);
check(delRes, { 'delete 200/204': (r) => r.status === 200 || r.status === 204 });
sleep(0.1);
}