@fluid-experimental/tree 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Common.d.ts +12 -6
- package/dist/Common.d.ts.map +1 -1
- package/dist/Common.js +14 -8
- package/dist/Common.js.map +1 -1
- package/dist/SharedTree.d.ts +12 -1
- package/dist/SharedTree.d.ts.map +1 -1
- package/dist/SharedTree.js +61 -11
- package/dist/SharedTree.js.map +1 -1
- package/dist/id-compressor/IdCompressor.d.ts.map +1 -1
- package/dist/id-compressor/IdCompressor.js +7 -11
- package/dist/id-compressor/IdCompressor.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/lib/Common.d.ts +12 -6
- package/lib/Common.d.ts.map +1 -1
- package/lib/Common.js +14 -8
- package/lib/Common.js.map +1 -1
- package/lib/SharedTree.d.ts +12 -1
- package/lib/SharedTree.d.ts.map +1 -1
- package/lib/SharedTree.js +61 -11
- package/lib/SharedTree.js.map +1 -1
- package/lib/id-compressor/IdCompressor.d.ts.map +1 -1
- package/lib/id-compressor/IdCompressor.js +7 -11
- package/lib/id-compressor/IdCompressor.js.map +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js.map +1 -1
- package/lib/test/IdCompressor.tests.js +2 -1
- package/lib/test/IdCompressor.tests.js.map +1 -1
- package/lib/test/fuzz/Generators.d.ts.map +1 -1
- package/lib/test/fuzz/Generators.js +20 -10
- package/lib/test/fuzz/Generators.js.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.d.ts.map +1 -1
- package/lib/test/fuzz/SharedTreeFuzzTests.js +55 -20
- package/lib/test/fuzz/SharedTreeFuzzTests.js.map +1 -1
- package/lib/test/fuzz/Types.d.ts +14 -4
- package/lib/test/fuzz/Types.d.ts.map +1 -1
- package/lib/test/fuzz/Types.js.map +1 -1
- package/lib/test/utilities/PendingLocalStateTests.d.ts.map +1 -1
- package/lib/test/utilities/PendingLocalStateTests.js +199 -56
- package/lib/test/utilities/PendingLocalStateTests.js.map +1 -1
- package/lib/test/utilities/TestUtilities.d.ts +12 -1
- package/lib/test/utilities/TestUtilities.d.ts.map +1 -1
- package/lib/test/utilities/TestUtilities.js +12 -2
- package/lib/test/utilities/TestUtilities.js.map +1 -1
- package/package.json +17 -17
- package/src/Common.ts +14 -8
- package/src/SharedTree.ts +90 -12
- package/src/id-compressor/IdCompressor.ts +9 -11
- package/src/index.ts +1 -0
|
@@ -3,19 +3,11 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
import { expect } from 'chai';
|
|
6
|
-
import { requestFluidObject } from '@fluidframework/runtime-utils';
|
|
7
6
|
import { fail } from '../../Common';
|
|
8
7
|
import { WriteFormat } from '../../persisted-types';
|
|
9
8
|
import { Change, StablePlace } from '../../ChangeTypes';
|
|
10
|
-
import { getEditLogInternal, setUpTestTree, stabilizeEdit, } from './TestUtilities';
|
|
11
|
-
|
|
12
|
-
await provider.ensureSynchronized();
|
|
13
|
-
await provider.opProcessingController.pauseProcessing(container);
|
|
14
|
-
const actionReturn = action();
|
|
15
|
-
const pendingLocalState = container.closeAndGetPendingLocalState();
|
|
16
|
-
provider.opProcessingController.resumeProcessing(container);
|
|
17
|
-
return { actionReturn, pendingLocalState };
|
|
18
|
-
}
|
|
9
|
+
import { applyNoop, getEditLogInternal, setUpTestTree, stabilizeEdit, withContainerOffline, } from './TestUtilities';
|
|
10
|
+
import { SimpleTestTree } from './TestNode';
|
|
19
11
|
/**
|
|
20
12
|
* Runs a test suite for SharedTree's ability to apply pending local state stashed by the host.
|
|
21
13
|
* See documentation on `applyStashedOp`.
|
|
@@ -24,47 +16,7 @@ async function withContainerOffline(provider, container, action) {
|
|
|
24
16
|
export function runPendingLocalStateTests(title, setUpLocalServerTestSharedTree) {
|
|
25
17
|
describe(title, () => {
|
|
26
18
|
const documentId = 'documentId';
|
|
27
|
-
|
|
28
|
-
[WriteFormat.v0_0_2].forEach((writeFormat) => {
|
|
29
|
-
it(`is applied to all connected containers (v${writeFormat})`, async () => {
|
|
30
|
-
var _a, _b, _c;
|
|
31
|
-
const { container, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({
|
|
32
|
-
id: documentId,
|
|
33
|
-
writeFormat,
|
|
34
|
-
});
|
|
35
|
-
const testTree = setUpTestTree(tree);
|
|
36
|
-
const { tree: tree2 } = await setUpLocalServerTestSharedTree({
|
|
37
|
-
id: documentId,
|
|
38
|
-
testObjectProvider,
|
|
39
|
-
writeFormat,
|
|
40
|
-
});
|
|
41
|
-
const url = (_a = (await container.getAbsoluteUrl('/'))) !== null && _a !== void 0 ? _a : fail('Container unable to resolve "/".');
|
|
42
|
-
await testObjectProvider.ensureSynchronized();
|
|
43
|
-
const initialEditLogLength = tree.edits.length;
|
|
44
|
-
const { pendingLocalState, actionReturn: edit } = await withContainerOffline(testObjectProvider, container, () => tree.applyEdit(...Change.insertTree(testTree.buildLeaf(), StablePlace.after(testTree.left))));
|
|
45
|
-
await testObjectProvider.ensureSynchronized();
|
|
46
|
-
const leftTraitAfterOfflineClose = tree2.currentView.getTrait(testTree.left.traitLocation.translate(tree2));
|
|
47
|
-
const loader = testObjectProvider.makeTestLoader();
|
|
48
|
-
// Simulate reconnect of user 1; a new container will be created which passes the stashed local state in its
|
|
49
|
-
// load request.
|
|
50
|
-
const container3 = await loader.resolve({ url }, pendingLocalState);
|
|
51
|
-
const dataObject3 = await requestFluidObject(container3, '/');
|
|
52
|
-
const tree3 = await dataObject3.getSharedObject(documentId);
|
|
53
|
-
expect(tree3.edits.isLocalEdit(edit.id)).to.be.true; // Kludge
|
|
54
|
-
await testObjectProvider.ensureSynchronized();
|
|
55
|
-
expect(leftTraitAfterOfflineClose.length).to.equal(1, 'Second tree should not receive edits made by first tree after it went offline.');
|
|
56
|
-
expect(tree3.currentView.getTrait(testTree.left.traitLocation.translate(tree3)).length).to.equal(2, 'Tree which loaded with stashed pending edits should apply them.');
|
|
57
|
-
expect(tree2.currentView.getTrait(testTree.left.traitLocation.translate(tree2)).length).to.equal(2, 'Tree collaborating with a client that applies stashed pending edits should see them.');
|
|
58
|
-
const stableEdit = stabilizeEdit(tree, edit);
|
|
59
|
-
expect(stabilizeEdit(tree2, (_b = (await getEditLogInternal(tree2).tryGetEdit(edit.id))) !== null && _b !== void 0 ? _b : fail())).to.deep.equal(stableEdit);
|
|
60
|
-
expect(stabilizeEdit(tree3, (_c = (await getEditLogInternal(tree3).tryGetEdit(edit.id))) !== null && _c !== void 0 ? _c : fail())).to.deep.equal(stableEdit);
|
|
61
|
-
expect(tree2.edits.length).to.equal(initialEditLogLength + 1);
|
|
62
|
-
expect(tree3.edits.length).to.equal(initialEditLogLength + 1);
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
it('Deals with stashed handle ops gracefully', async () => {
|
|
66
|
-
var _a;
|
|
67
|
-
// Setup
|
|
19
|
+
it('deals with stashed handle ops gracefully', async () => {
|
|
68
20
|
const { container, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({
|
|
69
21
|
id: documentId,
|
|
70
22
|
writeFormat: WriteFormat.v0_1_1,
|
|
@@ -75,7 +27,6 @@ export function runPendingLocalStateTests(title, setUpLocalServerTestSharedTree)
|
|
|
75
27
|
testObjectProvider,
|
|
76
28
|
writeFormat: WriteFormat.v0_1_1,
|
|
77
29
|
});
|
|
78
|
-
const url = (_a = (await container.getAbsoluteUrl('/'))) !== null && _a !== void 0 ? _a : fail('Container unable to resolve "/".');
|
|
79
30
|
await testObjectProvider.ensureSynchronized();
|
|
80
31
|
await testObjectProvider.opProcessingController.pauseProcessing();
|
|
81
32
|
// Generate enough edits to cause a chunk upload.
|
|
@@ -91,16 +42,208 @@ export function runPendingLocalStateTests(title, setUpLocalServerTestSharedTree)
|
|
|
91
42
|
await testObjectProvider.opProcessingController.processOutgoing(container);
|
|
92
43
|
await testObjectProvider.opProcessingController.processIncoming(container);
|
|
93
44
|
const pendingLocalState = container.closeAndGetPendingLocalState();
|
|
94
|
-
const
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
45
|
+
const { tree: tree2 } = await setUpLocalServerTestSharedTree({
|
|
46
|
+
testObjectProvider,
|
|
47
|
+
pendingLocalState,
|
|
48
|
+
id: documentId,
|
|
49
|
+
writeFormat: WriteFormat.v0_1_1,
|
|
50
|
+
});
|
|
98
51
|
await testObjectProvider.ensureSynchronized();
|
|
99
52
|
const editLog = tree2.edits;
|
|
100
53
|
const unuploadedEditChunks = Array.from(editLog.getEditChunksReadyForUpload());
|
|
101
54
|
expect(unuploadedEditChunks.length).to.equal(0);
|
|
102
55
|
expect(editLog.getEditLogSummary().editChunks.length).to.equal(2);
|
|
103
56
|
});
|
|
57
|
+
it('applies and submits ops from 0.0.2 in 0.0.2', async () => applyStashedOp(WriteFormat.v0_0_2, WriteFormat.v0_0_2));
|
|
58
|
+
it('applies and submits ops from 0.0.2 in 0.1.1', async () => applyStashedOp(WriteFormat.v0_0_2, WriteFormat.v0_1_1));
|
|
59
|
+
it('applies and submits ops from 0.1.1 in 0.0.2 (via upgrade)', async () => applyStashedOp(WriteFormat.v0_1_1, WriteFormat.v0_0_2));
|
|
60
|
+
it('applies and submits ops from 0.1.1 in 0.1.1', async () => applyStashedOp(WriteFormat.v0_1_1, WriteFormat.v0_1_1));
|
|
61
|
+
async function applyStashedOp(treeVersion, opVersion) {
|
|
62
|
+
var _a, _b;
|
|
63
|
+
const { container: stashingContainer, tree: stashingTree, testObjectProvider, } = await setUpLocalServerTestSharedTree({
|
|
64
|
+
id: documentId,
|
|
65
|
+
writeFormat: opVersion,
|
|
66
|
+
});
|
|
67
|
+
const stashingTestTree = setUpTestTree(stashingTree);
|
|
68
|
+
const { tree: observerTree } = await setUpLocalServerTestSharedTree({
|
|
69
|
+
id: documentId,
|
|
70
|
+
testObjectProvider,
|
|
71
|
+
writeFormat: treeVersion,
|
|
72
|
+
});
|
|
73
|
+
await testObjectProvider.ensureSynchronized();
|
|
74
|
+
const initialEditLogLength = stashingTree.edits.length;
|
|
75
|
+
const insertedLeafLabel = 'leaf';
|
|
76
|
+
const insertedLeafNodeId = stashingTestTree.generateNodeId('insertedLeafId');
|
|
77
|
+
const insertedLeafStableId = stashingTestTree.convertToStableNodeId(insertedLeafNodeId);
|
|
78
|
+
const { pendingLocalState, actionReturn: edit } = await withContainerOffline(testObjectProvider, stashingContainer, () => stashingTree.applyEdit(...Change.insertTree(Object.assign(Object.assign({}, stashingTestTree.buildLeaf()), { traits: {
|
|
79
|
+
[insertedLeafLabel]: stashingTestTree.buildLeaf(insertedLeafNodeId),
|
|
80
|
+
} }), StablePlace.after(stashingTestTree.left))));
|
|
81
|
+
await testObjectProvider.ensureSynchronized();
|
|
82
|
+
const observerAfterStash = observerTree.currentView;
|
|
83
|
+
// Simulate reconnect of user 1; a new container will be created which passes the stashed local state in its
|
|
84
|
+
// load request.
|
|
85
|
+
const { tree: stashingTree2 } = await setUpLocalServerTestSharedTree({
|
|
86
|
+
testObjectProvider,
|
|
87
|
+
pendingLocalState,
|
|
88
|
+
id: documentId,
|
|
89
|
+
writeFormat: treeVersion,
|
|
90
|
+
});
|
|
91
|
+
expect(stashingTree2.edits.isLocalEdit(edit.id)).to.be.true; // Kludge
|
|
92
|
+
await testObjectProvider.ensureSynchronized();
|
|
93
|
+
await testObjectProvider.ensureSynchronized(); // Synchronize twice in case stashed ops caused an upgrade round-trip
|
|
94
|
+
function tryGetInsertedLeafId(view) {
|
|
95
|
+
const rootNode = view.getViewNode(view.getTrait({ parent: view.root, label: SimpleTestTree.traitLabel })[0]);
|
|
96
|
+
const leftTrait = view.getTrait({ parent: rootNode.identifier, label: SimpleTestTree.leftTraitLabel });
|
|
97
|
+
if (leftTrait.length !== 2) {
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
const insertedParent = view.tryGetViewNode(leftTrait[1]);
|
|
101
|
+
if (insertedParent === undefined) {
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
return view.getTrait({ parent: insertedParent.identifier, label: insertedLeafLabel })[0];
|
|
105
|
+
}
|
|
106
|
+
expect(tryGetInsertedLeafId(observerAfterStash)).to.equal(undefined, 'Observing tree should not receive edits made by the stashing tree after it went offline.');
|
|
107
|
+
expect(tryGetInsertedLeafId(stashingTree2.currentView)).to.equal(stashingTree2.convertToNodeId(insertedLeafStableId), 'Tree which loaded with stashed pending edits should apply them correctly.');
|
|
108
|
+
expect(tryGetInsertedLeafId(stashingTree.currentView)).to.equal(stashingTree.convertToNodeId(insertedLeafStableId), 'Tree collaborating with a client that applies stashed pending edits should also apply them.');
|
|
109
|
+
const stableEdit = stabilizeEdit(stashingTree, edit);
|
|
110
|
+
expect(stabilizeEdit(observerTree, (_a = (await getEditLogInternal(observerTree).tryGetEdit(edit.id))) !== null && _a !== void 0 ? _a : fail())).to.deep.equal(stableEdit);
|
|
111
|
+
expect(stabilizeEdit(stashingTree2, (_b = (await getEditLogInternal(stashingTree2).tryGetEdit(edit.id))) !== null && _b !== void 0 ? _b : fail())).to.deep.equal(stableEdit);
|
|
112
|
+
expect(observerTree.edits.length).to.equal(initialEditLogLength + 1);
|
|
113
|
+
expect(stashingTree2.edits.length).to.equal(initialEditLogLength + 1);
|
|
114
|
+
}
|
|
115
|
+
it('works across summaries', async () => {
|
|
116
|
+
const smallTreeTraitLabel = '3b9e2dd8-def4-45fb-88bc-0df48df62314';
|
|
117
|
+
// 1. Create a client
|
|
118
|
+
const { testObjectProvider, tree: tree0 } = await setUpLocalServerTestSharedTree({
|
|
119
|
+
id: documentId,
|
|
120
|
+
writeFormat: WriteFormat.v0_0_2,
|
|
121
|
+
});
|
|
122
|
+
// 2. A second client joins
|
|
123
|
+
let tree;
|
|
124
|
+
let container;
|
|
125
|
+
({ container, tree } = await setUpLocalServerTestSharedTree({
|
|
126
|
+
id: documentId,
|
|
127
|
+
testObjectProvider,
|
|
128
|
+
writeFormat: WriteFormat.v0_0_2,
|
|
129
|
+
}));
|
|
130
|
+
expect(countSmallTrees(tree0)).to.equal(0);
|
|
131
|
+
expect(countSmallTrees(tree)).to.equal(0);
|
|
132
|
+
// 3. The second client creates stashed ops and rejoins after a summary
|
|
133
|
+
await waitForSummary(container);
|
|
134
|
+
({ tree, container } = await stash(container, () => insertSmallTree(tree)));
|
|
135
|
+
await testObjectProvider.ensureSynchronized();
|
|
136
|
+
expect(countSmallTrees(tree0)).to.equal(1);
|
|
137
|
+
expect(countSmallTrees(tree)).to.equal(1);
|
|
138
|
+
// 4. A third client joins, stashes and rejoins
|
|
139
|
+
const { container: container2, tree: tree2 } = await setUpLocalServerTestSharedTree({
|
|
140
|
+
id: documentId,
|
|
141
|
+
testObjectProvider,
|
|
142
|
+
writeFormat: WriteFormat.v0_0_2,
|
|
143
|
+
});
|
|
144
|
+
await stash(container2, () => insertSmallTree(tree2));
|
|
145
|
+
await testObjectProvider.ensureSynchronized();
|
|
146
|
+
expect(countSmallTrees(tree0)).to.equal(2);
|
|
147
|
+
expect(countSmallTrees(tree)).to.equal(2);
|
|
148
|
+
expect(countSmallTrees(tree2)).to.equal(2);
|
|
149
|
+
// Tolerate `InitialElectedClientNotFound` error (TODO:#1120)
|
|
150
|
+
const events = testObjectProvider.logger.reportAndClearTrackedEvents();
|
|
151
|
+
expect(events.unexpectedErrors.length).to.equal(1);
|
|
152
|
+
expect(events.unexpectedErrors[0].eventName).to.equal('fluid:telemetry:OrderedClientElection:InitialElectedClientNotFound');
|
|
153
|
+
/** Go offline, do something, then rejoin with pending local state */
|
|
154
|
+
async function stash(container, action) {
|
|
155
|
+
const { pendingLocalState } = await withContainerOffline(testObjectProvider, container, () => {
|
|
156
|
+
action();
|
|
157
|
+
});
|
|
158
|
+
return setUpLocalServerTestSharedTree({
|
|
159
|
+
id: documentId,
|
|
160
|
+
testObjectProvider,
|
|
161
|
+
writeFormat: WriteFormat.v0_0_2,
|
|
162
|
+
pendingLocalState,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
async function waitForSummary(container) {
|
|
166
|
+
return new Promise((resolve, reject) => {
|
|
167
|
+
let summarized = false;
|
|
168
|
+
container.on('op', (op) => {
|
|
169
|
+
if (op.type === 'summarize') {
|
|
170
|
+
summarized = true;
|
|
171
|
+
}
|
|
172
|
+
else if (summarized && op.type === 'summaryAck') {
|
|
173
|
+
resolve();
|
|
174
|
+
}
|
|
175
|
+
else if (op.type === 'summaryNack') {
|
|
176
|
+
reject(new Error('summaryNack'));
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
/** Insert some arbitrary data */
|
|
182
|
+
function insertSmallTree(tree) {
|
|
183
|
+
return tree.applyEdit(Change.insertTree([
|
|
184
|
+
{
|
|
185
|
+
definition: '7335ea74-c92f-47f4-8f00-376a306796f4',
|
|
186
|
+
traits: {
|
|
187
|
+
'e0901ba4-14c4-48e4-91a7-22a3068dc274': [
|
|
188
|
+
{
|
|
189
|
+
definition: '7335ea74-c92f-47f4-8f00-376a306796f4',
|
|
190
|
+
traits: {
|
|
191
|
+
'e0901ba4-14c4-48e4-91a7-22a3068dc274': [
|
|
192
|
+
{
|
|
193
|
+
definition: '7335ea74-c92f-47f4-8f00-376a306796f4',
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
],
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
definition: '7335ea74-c92f-47f4-8f00-376a306796f4',
|
|
203
|
+
traits: {
|
|
204
|
+
'e0901ba4-14c4-48e4-91a7-22a3068dc274': [
|
|
205
|
+
{
|
|
206
|
+
definition: '7335ea74-c92f-47f4-8f00-376a306796f4',
|
|
207
|
+
traits: {
|
|
208
|
+
'e0901ba4-14c4-48e4-91a7-22a3068dc274': [
|
|
209
|
+
{
|
|
210
|
+
definition: '7335ea74-c92f-47f4-8f00-376a306796f4',
|
|
211
|
+
},
|
|
212
|
+
],
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
},
|
|
217
|
+
},
|
|
218
|
+
], StablePlace.atEndOf({
|
|
219
|
+
label: smallTreeTraitLabel,
|
|
220
|
+
parent: tree.currentView.root,
|
|
221
|
+
}))).id;
|
|
222
|
+
}
|
|
223
|
+
/** Counts the number of trees that were inserted by `insertSmallTree` */
|
|
224
|
+
function countSmallTrees(tree) {
|
|
225
|
+
return (tree.currentView.getTrait({
|
|
226
|
+
label: smallTreeTraitLabel,
|
|
227
|
+
parent: tree.currentView.root,
|
|
228
|
+
}).length / 2);
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
it('cleans up temporary translation state', async () => {
|
|
232
|
+
// Glass box test to ensure that SharedTree doesn't hold on to temporary stashed op
|
|
233
|
+
// translation state for longer than necessary
|
|
234
|
+
function clearedTemporaryStashState(tree) {
|
|
235
|
+
return tree.stashedIdCompressor === null;
|
|
236
|
+
}
|
|
237
|
+
const { container: stashingContainer, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({});
|
|
238
|
+
await testObjectProvider.ensureSynchronized();
|
|
239
|
+
const { pendingLocalState } = await withContainerOffline(testObjectProvider, stashingContainer, () => applyNoop(tree));
|
|
240
|
+
await testObjectProvider.ensureSynchronized();
|
|
241
|
+
const { tree: tree2 } = await setUpLocalServerTestSharedTree({
|
|
242
|
+
testObjectProvider,
|
|
243
|
+
pendingLocalState,
|
|
244
|
+
});
|
|
245
|
+
expect(clearedTemporaryStashState(tree2)).to.be.true;
|
|
246
|
+
});
|
|
104
247
|
});
|
|
105
248
|
}
|
|
106
249
|
//# sourceMappingURL=PendingLocalStateTests.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PendingLocalStateTests.js","sourceRoot":"","sources":["../../../src/test/utilities/PendingLocalStateTests.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { expect } from 'chai';\nimport { IContainer } from '@fluidframework/container-definitions';\nimport { requestFluidObject } from '@fluidframework/runtime-utils';\nimport { ITestFluidObject, ITestObjectProvider } from '@fluidframework/test-utils';\nimport { fail } from '../../Common';\nimport { ChangeInternal, Edit, WriteFormat } from '../../persisted-types';\nimport type { EditLog } from '../../EditLog';\nimport { SharedTree } from '../../SharedTree';\nimport { Change, StablePlace } from '../../ChangeTypes';\nimport {\n\tgetEditLogInternal,\n\tLocalServerSharedTreeTestingComponents,\n\tLocalServerSharedTreeTestingOptions,\n\tsetUpTestTree,\n\tstabilizeEdit,\n} from './TestUtilities';\n\nasync function withContainerOffline<TReturn>(\n\tprovider: ITestObjectProvider,\n\tcontainer: IContainer,\n\taction: () => TReturn\n): Promise<{ actionReturn: TReturn; pendingLocalState: string }> {\n\tawait provider.ensureSynchronized();\n\tawait provider.opProcessingController.pauseProcessing(container);\n\tconst actionReturn = action();\n\tconst pendingLocalState = container.closeAndGetPendingLocalState();\n\tprovider.opProcessingController.resumeProcessing(container);\n\treturn { actionReturn, pendingLocalState };\n}\n\n/**\n * Runs a test suite for SharedTree's ability to apply pending local state stashed by the host.\n * See documentation on `applyStashedOp`.\n * This suite can be used to test other implementations that aim to fulfill `SharedTree`'s contract.\n */\nexport function runPendingLocalStateTests(\n\ttitle: string,\n\tsetUpLocalServerTestSharedTree: (\n\t\toptions: LocalServerSharedTreeTestingOptions\n\t) => Promise<LocalServerSharedTreeTestingComponents>\n) {\n\tdescribe(title, () => {\n\t\tconst documentId = 'documentId';\n\t\t/* TODO: Enable when stashed ops are supported: WriteFormat.v0_1_1 */\n\t\t[WriteFormat.v0_0_2].forEach((writeFormat) => {\n\t\t\tit(`is applied to all connected containers (v${writeFormat})`, async () => {\n\t\t\t\tconst { container, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({\n\t\t\t\t\tid: documentId,\n\t\t\t\t\twriteFormat,\n\t\t\t\t});\n\t\t\t\tconst testTree = setUpTestTree(tree);\n\t\t\t\tconst { tree: tree2 } = await setUpLocalServerTestSharedTree({\n\t\t\t\t\tid: documentId,\n\t\t\t\t\ttestObjectProvider,\n\t\t\t\t\twriteFormat,\n\t\t\t\t});\n\t\t\t\tconst url = (await container.getAbsoluteUrl('/')) ?? fail('Container unable to resolve \"/\".');\n\t\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\t\tconst initialEditLogLength = tree.edits.length;\n\n\t\t\t\tconst { pendingLocalState, actionReturn: edit } = await withContainerOffline(\n\t\t\t\t\ttestObjectProvider,\n\t\t\t\t\tcontainer,\n\t\t\t\t\t() => tree.applyEdit(...Change.insertTree(testTree.buildLeaf(), StablePlace.after(testTree.left)))\n\t\t\t\t);\n\t\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\t\tconst leftTraitAfterOfflineClose = tree2.currentView.getTrait(\n\t\t\t\t\ttestTree.left.traitLocation.translate(tree2)\n\t\t\t\t);\n\t\t\t\tconst loader = testObjectProvider.makeTestLoader();\n\n\t\t\t\t// Simulate reconnect of user 1; a new container will be created which passes the stashed local state in its\n\t\t\t\t// load request.\n\t\t\t\tconst container3 = await loader.resolve({ url }, pendingLocalState);\n\t\t\t\tconst dataObject3 = await requestFluidObject<ITestFluidObject>(container3, '/');\n\t\t\t\tconst tree3 = await dataObject3.getSharedObject<SharedTree>(documentId);\n\t\t\t\texpect((tree3.edits as unknown as EditLog<ChangeInternal>).isLocalEdit(edit.id)).to.be.true; // Kludge\n\n\t\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\t\texpect(leftTraitAfterOfflineClose.length).to.equal(\n\t\t\t\t\t1,\n\t\t\t\t\t'Second tree should not receive edits made by first tree after it went offline.'\n\t\t\t\t);\n\t\t\t\texpect(tree3.currentView.getTrait(testTree.left.traitLocation.translate(tree3)).length).to.equal(\n\t\t\t\t\t2,\n\t\t\t\t\t'Tree which loaded with stashed pending edits should apply them.'\n\t\t\t\t);\n\t\t\t\texpect(tree2.currentView.getTrait(testTree.left.traitLocation.translate(tree2)).length).to.equal(\n\t\t\t\t\t2,\n\t\t\t\t\t'Tree collaborating with a client that applies stashed pending edits should see them.'\n\t\t\t\t);\n\n\t\t\t\tconst stableEdit = stabilizeEdit(tree, edit as unknown as Edit<ChangeInternal>);\n\t\t\t\texpect(\n\t\t\t\t\tstabilizeEdit(tree2, (await getEditLogInternal(tree2).tryGetEdit(edit.id)) ?? fail())\n\t\t\t\t).to.deep.equal(stableEdit);\n\t\t\t\texpect(\n\t\t\t\t\tstabilizeEdit(tree3, (await getEditLogInternal(tree3).tryGetEdit(edit.id)) ?? fail())\n\t\t\t\t).to.deep.equal(stableEdit);\n\t\t\t\texpect(tree2.edits.length).to.equal(initialEditLogLength + 1);\n\t\t\t\texpect(tree3.edits.length).to.equal(initialEditLogLength + 1);\n\t\t\t});\n\t\t});\n\n\t\tit('Deals with stashed handle ops gracefully', async () => {\n\t\t\t// Setup\n\t\t\tconst { container, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\twriteFormat: WriteFormat.v0_1_1,\n\t\t\t});\n\t\t\tconst testTree = setUpTestTree(tree);\n\t\t\tawait setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\ttestObjectProvider,\n\t\t\t\twriteFormat: WriteFormat.v0_1_1,\n\t\t\t});\n\n\t\t\tconst url = (await container.getAbsoluteUrl('/')) ?? fail('Container unable to resolve \"/\".');\n\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\tawait testObjectProvider.opProcessingController.pauseProcessing();\n\t\t\t// Generate enough edits to cause a chunk upload.\n\t\t\tfor (let i = 0; i < (tree.edits as EditLog).editsPerChunk; i++) {\n\t\t\t\ttree.applyEdit(\n\t\t\t\t\t...Change.insertTree(testTree.buildLeaf(), StablePlace.atEndOf(testTree.left.traitLocation))\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Process all of those messages, sequencing them but without informing the container that they have been sequenced.\n\t\t\tawait testObjectProvider.opProcessingController.processOutgoing(container);\n\t\t\t// Inform the container that all of the edits it generated above have been sequenced, thereby filling an edit chunk\n\t\t\t// whose responsibility to upload is on the container.\n\t\t\tawait testObjectProvider.opProcessingController.processIncoming(container);\n\t\t\t// Process outgoing/incoming once more to handle the blob attach op.\n\t\t\tawait testObjectProvider.opProcessingController.processOutgoing(container);\n\t\t\tawait testObjectProvider.opProcessingController.processIncoming(container);\n\n\t\t\tconst pendingLocalState = container.closeAndGetPendingLocalState();\n\t\t\tconst loader = testObjectProvider.makeTestLoader();\n\n\t\t\tconst container2 = await loader.resolve({ url }, pendingLocalState);\n\t\t\tconst dataObject2 = await requestFluidObject<ITestFluidObject>(container2, '/');\n\t\t\tconst tree2 = await dataObject2.getSharedObject<SharedTree>(documentId);\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\tconst editLog = tree2.edits as EditLog;\n\t\t\tconst unuploadedEditChunks = Array.from(editLog.getEditChunksReadyForUpload());\n\t\t\texpect(unuploadedEditChunks.length).to.equal(0);\n\t\t\texpect(editLog.getEditLogSummary().editChunks.length).to.equal(2);\n\t\t});\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"PendingLocalStateTests.js","sourceRoot":"","sources":["../../../src/test/utilities/PendingLocalStateTests.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { expect } from 'chai';\nimport { IContainer } from '@fluidframework/container-definitions';\nimport { fail } from '../../Common';\nimport { ChangeInternal, Edit, WriteFormat } from '../../persisted-types';\nimport type { EditLog } from '../../EditLog';\nimport { SharedTree } from '../../SharedTree';\nimport { Change, StablePlace } from '../../ChangeTypes';\nimport { TreeView } from '../../TreeView';\nimport { EditId, NodeId, TraitLabel } from '../../Identifiers';\nimport {\n\tapplyNoop,\n\tgetEditLogInternal,\n\tLocalServerSharedTreeTestingComponents,\n\tLocalServerSharedTreeTestingOptions,\n\tsetUpTestTree,\n\tstabilizeEdit,\n\twithContainerOffline,\n} from './TestUtilities';\nimport { SimpleTestTree } from './TestNode';\n\n/**\n * Runs a test suite for SharedTree's ability to apply pending local state stashed by the host.\n * See documentation on `applyStashedOp`.\n * This suite can be used to test other implementations that aim to fulfill `SharedTree`'s contract.\n */\nexport function runPendingLocalStateTests(\n\ttitle: string,\n\tsetUpLocalServerTestSharedTree: (\n\t\toptions: LocalServerSharedTreeTestingOptions\n\t) => Promise<LocalServerSharedTreeTestingComponents>\n) {\n\tdescribe(title, () => {\n\t\tconst documentId = 'documentId';\n\n\t\tit('deals with stashed handle ops gracefully', async () => {\n\t\t\tconst { container, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\twriteFormat: WriteFormat.v0_1_1,\n\t\t\t});\n\t\t\tconst testTree = setUpTestTree(tree);\n\t\t\tawait setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\ttestObjectProvider,\n\t\t\t\twriteFormat: WriteFormat.v0_1_1,\n\t\t\t});\n\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\tawait testObjectProvider.opProcessingController.pauseProcessing();\n\t\t\t// Generate enough edits to cause a chunk upload.\n\t\t\tfor (let i = 0; i < (tree.edits as EditLog).editsPerChunk; i++) {\n\t\t\t\ttree.applyEdit(\n\t\t\t\t\t...Change.insertTree(testTree.buildLeaf(), StablePlace.atEndOf(testTree.left.traitLocation))\n\t\t\t\t);\n\t\t\t}\n\t\t\t// Process all of those messages, sequencing them but without informing the container that they have been sequenced.\n\t\t\tawait testObjectProvider.opProcessingController.processOutgoing(container);\n\t\t\t// Inform the container that all of the edits it generated above have been sequenced, thereby filling an edit chunk\n\t\t\t// whose responsibility to upload is on the container.\n\t\t\tawait testObjectProvider.opProcessingController.processIncoming(container);\n\t\t\t// Process outgoing/incoming once more to handle the blob attach op.\n\t\t\tawait testObjectProvider.opProcessingController.processOutgoing(container);\n\t\t\tawait testObjectProvider.opProcessingController.processIncoming(container);\n\n\t\t\tconst pendingLocalState = container.closeAndGetPendingLocalState();\n\t\t\tconst { tree: tree2 } = await setUpLocalServerTestSharedTree({\n\t\t\t\ttestObjectProvider,\n\t\t\t\tpendingLocalState,\n\t\t\t\tid: documentId,\n\t\t\t\twriteFormat: WriteFormat.v0_1_1,\n\t\t\t});\n\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\tconst editLog = tree2.edits as EditLog;\n\t\t\tconst unuploadedEditChunks = Array.from(editLog.getEditChunksReadyForUpload());\n\t\t\texpect(unuploadedEditChunks.length).to.equal(0);\n\t\t\texpect(editLog.getEditLogSummary().editChunks.length).to.equal(2);\n\t\t});\n\n\t\tit('applies and submits ops from 0.0.2 in 0.0.2', async () =>\n\t\t\tapplyStashedOp(WriteFormat.v0_0_2, WriteFormat.v0_0_2));\n\t\tit('applies and submits ops from 0.0.2 in 0.1.1', async () =>\n\t\t\tapplyStashedOp(WriteFormat.v0_0_2, WriteFormat.v0_1_1));\n\t\tit('applies and submits ops from 0.1.1 in 0.0.2 (via upgrade)', async () =>\n\t\t\tapplyStashedOp(WriteFormat.v0_1_1, WriteFormat.v0_0_2));\n\t\tit('applies and submits ops from 0.1.1 in 0.1.1', async () =>\n\t\t\tapplyStashedOp(WriteFormat.v0_1_1, WriteFormat.v0_1_1));\n\n\t\tasync function applyStashedOp(treeVersion: WriteFormat, opVersion: WriteFormat): Promise<void> {\n\t\t\tconst {\n\t\t\t\tcontainer: stashingContainer,\n\t\t\t\ttree: stashingTree,\n\t\t\t\ttestObjectProvider,\n\t\t\t} = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\twriteFormat: opVersion,\n\t\t\t});\n\t\t\tconst stashingTestTree = setUpTestTree(stashingTree);\n\t\t\tconst { tree: observerTree } = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\ttestObjectProvider,\n\t\t\t\twriteFormat: treeVersion,\n\t\t\t});\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\tconst initialEditLogLength = stashingTree.edits.length;\n\n\t\t\tconst insertedLeafLabel = 'leaf' as TraitLabel;\n\t\t\tconst insertedLeafNodeId = stashingTestTree.generateNodeId('insertedLeafId');\n\t\t\tconst insertedLeafStableId = stashingTestTree.convertToStableNodeId(insertedLeafNodeId);\n\t\t\tconst { pendingLocalState, actionReturn: edit } = await withContainerOffline(\n\t\t\t\ttestObjectProvider,\n\t\t\t\tstashingContainer,\n\t\t\t\t() =>\n\t\t\t\t\tstashingTree.applyEdit(\n\t\t\t\t\t\t...Change.insertTree(\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t...stashingTestTree.buildLeaf(),\n\t\t\t\t\t\t\t\ttraits: {\n\t\t\t\t\t\t\t\t\t[insertedLeafLabel]: stashingTestTree.buildLeaf(insertedLeafNodeId),\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tStablePlace.after(stashingTestTree.left)\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t);\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\tconst observerAfterStash = observerTree.currentView;\n\n\t\t\t// Simulate reconnect of user 1; a new container will be created which passes the stashed local state in its\n\t\t\t// load request.\n\t\t\tconst { tree: stashingTree2 } = await setUpLocalServerTestSharedTree({\n\t\t\t\ttestObjectProvider,\n\t\t\t\tpendingLocalState,\n\t\t\t\tid: documentId,\n\t\t\t\twriteFormat: treeVersion,\n\t\t\t});\n\n\t\t\texpect((stashingTree2.edits as unknown as EditLog<ChangeInternal>).isLocalEdit(edit.id)).to.be.true; // Kludge\n\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\t\t\tawait testObjectProvider.ensureSynchronized(); // Synchronize twice in case stashed ops caused an upgrade round-trip\n\n\t\t\tfunction tryGetInsertedLeafId(view: TreeView): NodeId | undefined {\n\t\t\t\tconst rootNode = view.getViewNode(\n\t\t\t\t\tview.getTrait({ parent: view.root, label: SimpleTestTree.traitLabel })[0]\n\t\t\t\t);\n\t\t\t\tconst leftTrait = view.getTrait({ parent: rootNode.identifier, label: SimpleTestTree.leftTraitLabel });\n\t\t\t\tif (leftTrait.length !== 2) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tconst insertedParent = view.tryGetViewNode(leftTrait[1]);\n\t\t\t\tif (insertedParent === undefined) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\treturn view.getTrait({ parent: insertedParent.identifier, label: insertedLeafLabel })[0];\n\t\t\t}\n\n\t\t\texpect(tryGetInsertedLeafId(observerAfterStash)).to.equal(\n\t\t\t\tundefined,\n\t\t\t\t'Observing tree should not receive edits made by the stashing tree after it went offline.'\n\t\t\t);\n\t\t\texpect(tryGetInsertedLeafId(stashingTree2.currentView)).to.equal(\n\t\t\t\tstashingTree2.convertToNodeId(insertedLeafStableId),\n\t\t\t\t'Tree which loaded with stashed pending edits should apply them correctly.'\n\t\t\t);\n\t\t\texpect(tryGetInsertedLeafId(stashingTree.currentView)).to.equal(\n\t\t\t\tstashingTree.convertToNodeId(insertedLeafStableId),\n\t\t\t\t'Tree collaborating with a client that applies stashed pending edits should also apply them.'\n\t\t\t);\n\n\t\t\tconst stableEdit = stabilizeEdit(stashingTree, edit as unknown as Edit<ChangeInternal>);\n\t\t\texpect(\n\t\t\t\tstabilizeEdit(observerTree, (await getEditLogInternal(observerTree).tryGetEdit(edit.id)) ?? fail())\n\t\t\t).to.deep.equal(stableEdit);\n\n\t\t\texpect(\n\t\t\t\tstabilizeEdit(stashingTree2, (await getEditLogInternal(stashingTree2).tryGetEdit(edit.id)) ?? fail())\n\t\t\t).to.deep.equal(stableEdit);\n\n\t\t\texpect(observerTree.edits.length).to.equal(initialEditLogLength + 1);\n\t\t\texpect(stashingTree2.edits.length).to.equal(initialEditLogLength + 1);\n\t\t}\n\n\t\tit('works across summaries', async () => {\n\t\t\tconst smallTreeTraitLabel = '3b9e2dd8-def4-45fb-88bc-0df48df62314' as TraitLabel;\n\n\t\t\t// 1. Create a client\n\t\t\tconst { testObjectProvider, tree: tree0 } = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\twriteFormat: WriteFormat.v0_0_2,\n\t\t\t});\n\n\t\t\t// 2. A second client joins\n\t\t\tlet tree: SharedTree;\n\t\t\tlet container: IContainer;\n\t\t\t({ container, tree } = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\ttestObjectProvider,\n\t\t\t\twriteFormat: WriteFormat.v0_0_2,\n\t\t\t}));\n\n\t\t\texpect(countSmallTrees(tree0)).to.equal(0);\n\t\t\texpect(countSmallTrees(tree)).to.equal(0);\n\n\t\t\t// 3. The second client creates stashed ops and rejoins after a summary\n\t\t\tawait waitForSummary(container);\n\t\t\t({ tree, container } = await stash(container, () => insertSmallTree(tree)));\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\texpect(countSmallTrees(tree0)).to.equal(1);\n\t\t\texpect(countSmallTrees(tree)).to.equal(1);\n\n\t\t\t// 4. A third client joins, stashes and rejoins\n\t\t\tconst { container: container2, tree: tree2 } = await setUpLocalServerTestSharedTree({\n\t\t\t\tid: documentId,\n\t\t\t\ttestObjectProvider,\n\t\t\t\twriteFormat: WriteFormat.v0_0_2,\n\t\t\t});\n\n\t\t\tawait stash(container2, () => insertSmallTree(tree2));\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\texpect(countSmallTrees(tree0)).to.equal(2);\n\t\t\texpect(countSmallTrees(tree)).to.equal(2);\n\t\t\texpect(countSmallTrees(tree2)).to.equal(2);\n\n\t\t\t// Tolerate `InitialElectedClientNotFound` error (TODO:#1120)\n\t\t\tconst events = testObjectProvider.logger.reportAndClearTrackedEvents();\n\t\t\texpect(events.unexpectedErrors.length).to.equal(1);\n\t\t\texpect(events.unexpectedErrors[0].eventName).to.equal(\n\t\t\t\t'fluid:telemetry:OrderedClientElection:InitialElectedClientNotFound'\n\t\t\t);\n\n\t\t\t/** Go offline, do something, then rejoin with pending local state */\n\t\t\tasync function stash(\n\t\t\t\tcontainer: IContainer,\n\t\t\t\taction: () => void\n\t\t\t): Promise<{ tree: SharedTree; container: IContainer }> {\n\t\t\t\tconst { pendingLocalState } = await withContainerOffline(testObjectProvider, container, () => {\n\t\t\t\t\taction();\n\t\t\t\t});\n\t\t\t\treturn setUpLocalServerTestSharedTree({\n\t\t\t\t\tid: documentId,\n\t\t\t\t\ttestObjectProvider,\n\t\t\t\t\twriteFormat: WriteFormat.v0_0_2,\n\t\t\t\t\tpendingLocalState,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tasync function waitForSummary(container: IContainer): Promise<void> {\n\t\t\t\treturn new Promise((resolve, reject) => {\n\t\t\t\t\tlet summarized = false;\n\t\t\t\t\tcontainer.on('op', (op) => {\n\t\t\t\t\t\tif (op.type === 'summarize') {\n\t\t\t\t\t\t\tsummarized = true;\n\t\t\t\t\t\t} else if (summarized && op.type === 'summaryAck') {\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t} else if (op.type === 'summaryNack') {\n\t\t\t\t\t\t\treject(new Error('summaryNack'));\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t}\n\n\t\t\t/** Insert some arbitrary data */\n\t\t\tfunction insertSmallTree(tree: SharedTree): EditId {\n\t\t\t\treturn tree.applyEdit(\n\t\t\t\t\tChange.insertTree(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdefinition: '7335ea74-c92f-47f4-8f00-376a306796f4',\n\t\t\t\t\t\t\t\ttraits: {\n\t\t\t\t\t\t\t\t\t'e0901ba4-14c4-48e4-91a7-22a3068dc274': [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdefinition: '7335ea74-c92f-47f4-8f00-376a306796f4',\n\t\t\t\t\t\t\t\t\t\t\ttraits: {\n\t\t\t\t\t\t\t\t\t\t\t\t'e0901ba4-14c4-48e4-91a7-22a3068dc274': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdefinition: '7335ea74-c92f-47f4-8f00-376a306796f4',\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tdefinition: '7335ea74-c92f-47f4-8f00-376a306796f4',\n\t\t\t\t\t\t\t\ttraits: {\n\t\t\t\t\t\t\t\t\t'e0901ba4-14c4-48e4-91a7-22a3068dc274': [\n\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\tdefinition: '7335ea74-c92f-47f4-8f00-376a306796f4',\n\t\t\t\t\t\t\t\t\t\t\ttraits: {\n\t\t\t\t\t\t\t\t\t\t\t\t'e0901ba4-14c4-48e4-91a7-22a3068dc274': [\n\t\t\t\t\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tdefinition: '7335ea74-c92f-47f4-8f00-376a306796f4',\n\t\t\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t\tStablePlace.atEndOf({\n\t\t\t\t\t\t\tlabel: smallTreeTraitLabel,\n\t\t\t\t\t\t\tparent: tree.currentView.root,\n\t\t\t\t\t\t})\n\t\t\t\t\t)\n\t\t\t\t).id;\n\t\t\t}\n\n\t\t\t/** Counts the number of trees that were inserted by `insertSmallTree` */\n\t\t\tfunction countSmallTrees(tree: SharedTree): number {\n\t\t\t\treturn (\n\t\t\t\t\ttree.currentView.getTrait({\n\t\t\t\t\t\tlabel: smallTreeTraitLabel,\n\t\t\t\t\t\tparent: tree.currentView.root,\n\t\t\t\t\t}).length / 2\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\n\t\tit('cleans up temporary translation state', async () => {\n\t\t\t// Glass box test to ensure that SharedTree doesn't hold on to temporary stashed op\n\t\t\t// translation state for longer than necessary\n\t\t\tfunction clearedTemporaryStashState(tree: SharedTree): boolean {\n\t\t\t\treturn (tree as unknown as { stashedIdCompressor?: unknown }).stashedIdCompressor === null;\n\t\t\t}\n\n\t\t\tconst { container: stashingContainer, tree, testObjectProvider } = await setUpLocalServerTestSharedTree({});\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\tconst { pendingLocalState } = await withContainerOffline(testObjectProvider, stashingContainer, () =>\n\t\t\t\tapplyNoop(tree)\n\t\t\t);\n\t\t\tawait testObjectProvider.ensureSynchronized();\n\n\t\t\tconst { tree: tree2 } = await setUpLocalServerTestSharedTree({\n\t\t\t\ttestObjectProvider,\n\t\t\t\tpendingLocalState,\n\t\t\t});\n\n\t\t\texpect(clearedTemporaryStashState(tree2)).to.be.true;\n\t\t});\n\t});\n}\n"]}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { Container } from '@fluidframework/container-loader';
|
|
6
6
|
import { MockContainerRuntimeFactory, MockFluidDataStoreRuntime } from '@fluidframework/test-runtime-utils';
|
|
7
|
-
import { TestObjectProvider } from '@fluidframework/test-utils';
|
|
7
|
+
import { TestObjectProvider, ITestObjectProvider } from '@fluidframework/test-utils';
|
|
8
8
|
import { ITelemetryBaseLogger } from '@fluidframework/common-definitions';
|
|
9
9
|
import type { IContainer } from '@fluidframework/container-definitions';
|
|
10
10
|
import type { IFluidHandle, IRequestHeader } from '@fluidframework/core-interfaces';
|
|
@@ -125,6 +125,10 @@ export interface LocalServerSharedTreeTestingOptions {
|
|
|
125
125
|
* If set, uses the given id as the edit id for tree setup. Only has an effect if initialTree is also set.
|
|
126
126
|
*/
|
|
127
127
|
setupEditId?: EditId;
|
|
128
|
+
/**
|
|
129
|
+
* If set, will be passed to the container on load
|
|
130
|
+
*/
|
|
131
|
+
pendingLocalState?: string;
|
|
128
132
|
}
|
|
129
133
|
/**
|
|
130
134
|
* Sets up and returns an object of components useful for testing SharedTree with a local server.
|
|
@@ -188,4 +192,11 @@ export declare function spyOnSubmittedOps<Op extends SharedTreeOp | SharedTreeOp
|
|
|
188
192
|
* to ensure they load this summary version. Use the `LoaderHeader.version` header.
|
|
189
193
|
*/
|
|
190
194
|
export declare function waitForSummary(mainContainer: IContainer): Promise<string>;
|
|
195
|
+
/**
|
|
196
|
+
* Runs an action while the given container has been paused
|
|
197
|
+
*/
|
|
198
|
+
export declare function withContainerOffline<TReturn>(provider: ITestObjectProvider, container: IContainer, action: () => TReturn): Promise<{
|
|
199
|
+
actionReturn: TReturn;
|
|
200
|
+
pendingLocalState: string;
|
|
201
|
+
}>;
|
|
191
202
|
//# sourceMappingURL=TestUtilities.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TestUtilities.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/TestUtilities.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"TestUtilities.d.ts","sourceRoot":"","sources":["../../../src/test/utilities/TestUtilities.ts"],"names":[],"mappings":"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"}
|
|
@@ -113,7 +113,7 @@ afterEach(() => {
|
|
|
113
113
|
* Any TestObjectProvider created by this function will be reset after the test completes (via afterEach) hook.
|
|
114
114
|
*/
|
|
115
115
|
export async function setUpLocalServerTestSharedTree(options) {
|
|
116
|
-
const { blobs, headers, id, initialTree, testObjectProvider, setupEditId, summarizeHistory, writeFormat, uploadEditChunks, attributionId, } = options;
|
|
116
|
+
const { blobs, headers, id, initialTree, testObjectProvider, setupEditId, summarizeHistory, writeFormat, uploadEditChunks, attributionId, pendingLocalState, } = options;
|
|
117
117
|
const treeId = id !== null && id !== void 0 ? id : 'test';
|
|
118
118
|
let factory;
|
|
119
119
|
if (writeFormat === WriteFormat.v0_0_2) {
|
|
@@ -155,7 +155,7 @@ export async function setUpLocalServerTestSharedTree(options) {
|
|
|
155
155
|
const driver = new LocalServerTestDriver();
|
|
156
156
|
const loader = makeTestLoader(provider);
|
|
157
157
|
// Once ILoaderOptions is specificable, this should use `provider.loadTestContainer` instead.
|
|
158
|
-
container = (await loader.resolve({ url: await driver.createContainerUrl(treeId), headers }));
|
|
158
|
+
container = (await loader.resolve({ url: await driver.createContainerUrl(treeId), headers }, pendingLocalState));
|
|
159
159
|
await waitContainerToCatchUp(container);
|
|
160
160
|
}
|
|
161
161
|
else {
|
|
@@ -389,4 +389,14 @@ export async function waitForSummary(mainContainer) {
|
|
|
389
389
|
const ackedSummary = await summaryCollection.waitSummaryAck(deltaManager.lastSequenceNumber);
|
|
390
390
|
return ackedSummary.summaryAck.contents.handle;
|
|
391
391
|
}
|
|
392
|
+
/**
|
|
393
|
+
* Runs an action while the given container has been paused
|
|
394
|
+
*/
|
|
395
|
+
export async function withContainerOffline(provider, container, action) {
|
|
396
|
+
await provider.ensureSynchronized();
|
|
397
|
+
await provider.opProcessingController.pauseProcessing(container);
|
|
398
|
+
const actionReturn = action();
|
|
399
|
+
const pendingLocalState = container.closeAndGetPendingLocalState();
|
|
400
|
+
return { actionReturn, pendingLocalState };
|
|
401
|
+
}
|
|
392
402
|
//# sourceMappingURL=TestUtilities.js.map
|