Files
Oxicloud/tests/load/scenarios/subject_group_nested.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

74 lines
3.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// subject_group_nested.js — measures the worst-case AuthZ path: a user who
// is a direct member of the *innermost* group of a depth-N nested chain, and
// the grant is on the *outermost* group. Every AuthZ check has to expand the
// chain transitively. Pairs with share_cascade_rebac.js to attribute regressions
// to either the resource side (folder cascade) or the subject side (group
// expansion).
//
// Same depth-gradient idea as share_cascade_rebac: measure AuthZ cost at
// depth 1 / 4 / 8 / deep so we can see WHERE in the chain a regression
// lands. The subject-side expansion (group_member → leaf → mid → root group
// → grant) runs once per request regardless of folder depth, but the
// resource-side cascade (folder ancestors walked to find the grant) grows
// linearly with depth — so depth4/depth8/deep moving together while depth1
// stays flat would point at the resource side; all four moving together
// would point at the group-expansion path.
import { check } from 'k6';
import http from 'k6/http';
import { BASE, authParams } from '../lib/http.js';
import { login } from '../lib/auth.js';
import { thresholdsFromBaseline, loadManifest } from '../lib/metrics.js';
const manifest = loadManifest();
export const options = {
vus: 1,
// See folder_cascade.js for the iteration-count rationale: N=100 makes
// p99 a real percentile instead of the worst-of-the-batch.
iterations: 100,
thresholds: thresholdsFromBaseline('subject_group_nested'),
};
export function setup() {
const memberToken = login(manifest.group_member.username, manifest.group_member.password);
return { memberToken };
}
export default function (data) {
const { memberToken } = data;
const t = manifest.group_subtree;
// Baseline: group member fetches the folder the grant is directly on.
// Subject-side expansion runs (user → leaf → mid → root group → grant);
// resource-side walk is zero ancestors. Captures the constant subject-
// expansion overhead.
const d1 = http.get(
`${BASE}/api/folders/${t.root}/resources?resource_types=folder`,
authParams(memberToken, 'subject_group_nested.fetch_as_member_depth1'),
);
check(d1, { 'fetch root 200': (r) => r.status === 200 });
// Mid-tree: 4 folder ancestors walked + subject expansion.
const d4 = http.get(
`${BASE}/api/folders/${t.depth4}/resources?resource_types=folder`,
authParams(memberToken, 'subject_group_nested.fetch_as_member_depth4'),
);
check(d4, { 'fetch depth4 200': (r) => r.status === 200 });
// 8 folder ancestors walked + subject expansion.
const d8 = http.get(
`${BASE}/api/folders/${t.depth8}/resources?resource_types=folder`,
authParams(memberToken, 'subject_group_nested.fetch_as_member_depth8'),
);
check(d8, { 'fetch depth8 200': (r) => r.status === 200 });
// Worst case: full-depth folder cascade × full-chain subject expansion.
// group_member → leaf group → mid group → root group → grant → folder root → deepest.
const dD = http.get(
`${BASE}/api/folders/${t.deepest}/resources?resource_types=folder`,
authParams(memberToken, 'subject_group_nested.fetch_as_member_depth_deep'),
);
check(dD, { 'fetch deepest 200': (r) => r.status === 200 });
}