"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.annotateRange = void 0;
const assert_1 = require("assert");
const test_pairwise_generator_1 = require("@fluid-private/test-pairwise-generator");
const stochastic_test_utils_1 = require("@fluid-private/stochastic-test-utils");
const attributionPolicy_1 = require("../attributionPolicy.cjs");
const mergeTreeOperationRunner_1 = require("./mergeTreeOperationRunner.cjs");
const testClient_1 = require("./testClient.cjs");
const testClientLogger_1 = require("./testClientLogger.cjs");
const annotateRange = (client, opStart, opEnd) => client.annotateRangeLocal(opStart, opEnd, { trackedProp: client.longClientId });
exports.annotateRange = annotateRange;
const defaultOptions = {
    initLen: { min: 2, max: 4 },
    modLen: { min: 1, max: 8 },
    opsPerRoundRange: { min: 10, max: 40 },
    rounds: 10,
    operations: [mergeTreeOperationRunner_1.removeRange, exports.annotateRange, mergeTreeOperationRunner_1.insert],
    growthFunc: (input) => input * 2,
};
(0, stochastic_test_utils_1.describeFuzz)("MergeTree.Attribution", ({ testCount }) => {
    // Generate a list of single character client names, support up to 69 clients
    const clientNames = (0, mergeTreeOperationRunner_1.generateClientNames)();
    const rangeOptions = (0, mergeTreeOperationRunner_1.resolveRanges)(defaultOptions, defaultOptions.growthFunc);
    for (let extraSeed = 0; extraSeed < testCount; extraSeed++) {
        (0, test_pairwise_generator_1.generatePairwiseOptions)(rangeOptions).forEach(({ initLen, modLen, opsPerRoundRange }) => {
            it(`AttributionFarm_${initLen}_${modLen}_${opsPerRoundRange}`, async () => {
                const random = (0, stochastic_test_utils_1.makeRandom)(0xdeadbeef, initLen, modLen, extraSeed ?? 0);
                const clients = new Array(3).fill(0).map(() => new testClient_1.TestClient({
                    attribution: {
                        track: true,
                        policyFactory: (0, attributionPolicy_1.createPropertyTrackingAndInsertionAttributionPolicyFactory)("trackedProp"),
                    },
                }));
                clients.forEach((c, i) => c.startOrUpdateCollaboration(clientNames[i]));
                const getAttributionAtPosition = (client, pos) => {
                    const { segment, offset } = client.getContainingSegment(pos);
                    if (segment?.attribution === undefined || offset === undefined) {
                        return undefined;
                    }
                    const { attribution } = segment;
                    let channels;
                    const result = {
                        root: attribution.getAtOffset(offset),
                    };
                    for (const name of attribution.channelNames) {
                        (channels ?? (channels = {}))[name] = attribution.getAtOffset(offset, name);
                        result.channels = channels;
                    }
                    return channels;
                };
                const validateAnnotation = (reason, workload) => {
                    const preWorkload = testClientLogger_1.TestClientLogger.toString(clients);
                    workload();
                    const attributions = Array.from({ length: clients[0].getLength() }).map((_, i) => getAttributionAtPosition(clients[0], i));
                    for (let c = 1; c < clients.length; c++) {
                        for (let i = 0; i < clients[c].getLength(); i++) {
                            const attribution0 = attributions[i];
                            const attributionC = getAttributionAtPosition(clients[c], i);
                            if (attribution0 !== attributionC) {
                                assert_1.strict.deepEqual(attribution0, attributionC, `${reason}:\n${preWorkload}\n${testClientLogger_1.TestClientLogger.toString([
                                    clients[0],
                                    clients[c],
                                ])}`);
                            }
                        }
                    }
                };
                let seq = 0;
                validateAnnotation("Initialize", () => {
                    seq = (0, mergeTreeOperationRunner_1.runMergeTreeOperationRunner)(random, seq, clients, initLen, defaultOptions);
                });
                validateAnnotation("After Init Zamboni", () => {
                    // trigger zamboni multiple times as it is incremental
                    for (let i = clients[0].getCollabWindow().minSeq; i <= seq; i++) {
                        clients.forEach((c) => c.updateMinSeq(i));
                    }
                });
                validateAnnotation("After More Ops", () => {
                    seq = (0, mergeTreeOperationRunner_1.runMergeTreeOperationRunner)(random, seq, clients, modLen, defaultOptions);
                });
                validateAnnotation("After Final Zamboni", () => {
                    // trigger zamboni multiple times as it is incremental
                    for (let i = clients[0].getCollabWindow().minSeq; i <= seq; i++) {
                        clients.forEach((c) => c.updateMinSeq(i));
                    }
                });
            });
        });
    }
});
//# sourceMappingURL=client.attributionFarm.spec.cjs.map