Skip to content

Commit 049d44b

Browse files
Adding Spec Test Benchmark suite
1 parent fc2e967 commit 049d44b

File tree

2 files changed

+234
-2
lines changed

2 files changed

+234
-2
lines changed

packages/firestore/test/unit/specs/describe_spec.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ const NO_WEB_TAG = 'no-web';
3131
const NO_ANDROID_TAG = 'no-android';
3232
const NO_IOS_TAG = 'no-ios';
3333
const NO_LRU = 'no-lru';
34+
const BENCHMARK_TAG = 'benchmark';
3435
const KNOWN_TAGS = [
36+
BENCHMARK_TAG,
3537
EXCLUSIVE_TAG,
3638
PERSISTENCE_TAG,
3739
NO_WEB_TAG,
@@ -40,6 +42,9 @@ const KNOWN_TAGS = [
4042
NO_LRU
4143
];
4244

45+
// TOOD: Make this configurable with mocha options.
46+
const RUN_BENCHMARK_TESTS = false;
47+
4348
const WEB_SPEC_TEST_FILTER = (tags: string[]) =>
4449
tags.indexOf(NO_WEB_TAG) === -1;
4550

@@ -127,6 +132,8 @@ export function specTest(
127132
runner = it.only;
128133
} else if (!WEB_SPEC_TEST_FILTER(tags)) {
129134
runner = it.skip;
135+
} else if (tags.indexOf(BENCHMARK_TAG) >= 0 && !RUN_BENCHMARK_TESTS) {
136+
runner = it.skip;
130137
} else if (usePersistence && tags.indexOf('no-lru') !== -1) {
131138
// spec should have a comment explaining why it is being skipped.
132139
runner = it.skip;
@@ -135,8 +142,14 @@ export function specTest(
135142
}
136143
const mode = usePersistence ? '(Persistence)' : '(Memory)';
137144
const fullName = `${mode} ${name}`;
138-
runner(fullName, () => {
139-
return spec.runAsTest(fullName, usePersistence);
145+
runner(fullName, async () => {
146+
const start = Date.now();
147+
await spec.runAsTest(fullName, usePersistence);
148+
const end = Date.now();
149+
if (tags.indexOf(BENCHMARK_TAG) >= 0) {
150+
// tslint:disable-next-line:no-console
151+
console.log(`Runtime: ${end - start} ms.`);
152+
}
140153
});
141154
}
142155
} else {
Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
/**
2+
* Copyright 2017 Google Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
import { Query } from '../../../src/core/query';
18+
import { doc, orderBy, path } from '../../util/helpers';
19+
20+
import { describeSpec, specTest } from './describe_spec';
21+
import { spec } from './spec_builder';
22+
23+
const STEP_COUNT = 10;
24+
25+
describeSpec('Performance Tests:', ['benchmark'], () => {
26+
specTest('Insert a new document', [], () => {
27+
let steps = spec().withGCEnabled(false);
28+
for (let i = 0; i < STEP_COUNT; ++i) {
29+
steps = steps.userSets(`collection/{i}`, { doc: i }).writeAcks(i);
30+
}
31+
return steps;
32+
});
33+
34+
specTest('Insert a new document and wait for snapshot', [], () => {
35+
let version = 2;
36+
37+
let steps = spec().withGCEnabled(false);
38+
for (let i = 0; i < STEP_COUNT; ++i) {
39+
const query = Query.atPath(path(`collection/${i}`));
40+
const docLocal = doc(
41+
`collection/${i}`,
42+
0,
43+
{ doc: i },
44+
{ hasLocalMutations: true }
45+
);
46+
const docRemote = doc(`collection/${i}`, ++version, { doc: i });
47+
48+
steps = steps
49+
.userListens(query)
50+
.userSets(`collection/${i}`, { doc: i })
51+
.expectEvents(query, {
52+
added: [docLocal],
53+
fromCache: true,
54+
hasPendingWrites: true
55+
})
56+
.writeAcks(++version)
57+
.watchAcksFull(query, ++version, docRemote)
58+
.expectEvents(query, { metadata: [docRemote] })
59+
.userUnlistens(query)
60+
.watchRemoves(query);
61+
}
62+
return steps;
63+
});
64+
65+
specTest('Watch has cached mutations', [], () => {
66+
const cachedDocumentCount = 100;
67+
68+
const query = Query.atPath(path(`collection`)).addOrderBy(orderBy('v'));
69+
70+
let steps = spec().withGCEnabled(false);
71+
72+
const docs = [];
73+
74+
for (let i = 0; i < cachedDocumentCount; ++i) {
75+
steps.userSets(`collection/${i}`, { v: i });
76+
docs.push(
77+
doc(`collection/${i}`, 0, { v: i }, { hasLocalMutations: true })
78+
);
79+
}
80+
81+
for (let i = 1; i <= STEP_COUNT; ++i) {
82+
steps = steps
83+
.userListens(query)
84+
.expectEvents(query, {
85+
added: docs,
86+
fromCache: true,
87+
hasPendingWrites: true
88+
})
89+
.userUnlistens(query);
90+
}
91+
92+
return steps;
93+
});
94+
95+
specTest('Update a single document', [], () => {
96+
let steps = spec().withGCEnabled(false);
97+
98+
steps = steps.userSets(`collection/doc`, { v: 0 });
99+
for (let i = 1; i <= STEP_COUNT; ++i) {
100+
steps = steps.userPatches(`collection/doc`, { v: i }).writeAcks(i);
101+
}
102+
return steps;
103+
});
104+
105+
specTest(
106+
'Update a single document and wait for snapshot',
107+
[],
108+
() => {
109+
let version = 1;
110+
111+
const query = Query.atPath(path(`collection/doc`));
112+
let docLocal = doc(
113+
`collection/doc`,
114+
0,
115+
{ v: 0 },
116+
{ hasLocalMutations: true }
117+
);
118+
let docRemote = doc(`collection/doc`, ++version, { v: 0 });
119+
let lastRemoteVersion = version;
120+
121+
let steps = spec().withGCEnabled(false);
122+
123+
steps = steps
124+
.userListens(query)
125+
.userSets(`collection/doc`, { v: 0 })
126+
.expectEvents(query, {
127+
added: [docLocal],
128+
fromCache: true,
129+
hasPendingWrites: true
130+
})
131+
.writeAcks(++version)
132+
.watchAcksFull(query, ++version, docRemote)
133+
.expectEvents(query, { metadata: [docRemote] });
134+
135+
for (let i = 1; i <= STEP_COUNT; ++i) {
136+
docLocal = doc(
137+
`collection/doc`,
138+
lastRemoteVersion,
139+
{ v: i },
140+
{ hasLocalMutations: true }
141+
);
142+
docRemote = doc(`collection/doc`, ++version, { v: i });
143+
lastRemoteVersion = version;
144+
145+
steps = steps
146+
.userPatches(`collection/doc`, { v: i })
147+
.expectEvents(query, { modified: [docLocal], hasPendingWrites: true })
148+
.writeAcks(++version)
149+
.watchSends({ affects: [query] }, docRemote)
150+
.watchSnapshots(++version)
151+
.expectEvents(query, { metadata: [docRemote] });
152+
}
153+
return steps;
154+
}
155+
);
156+
157+
specTest('Watch sends 100 documents', [], () => {
158+
let version = 1;
159+
const documentsPerStep = 100;
160+
161+
const query = Query.atPath(path(`collection`)).addOrderBy(orderBy('v'));
162+
163+
let steps = spec().withGCEnabled(false);
164+
165+
steps = steps
166+
.userListens(query)
167+
.watchAcksFull(query, version)
168+
.expectEvents(query, {});
169+
170+
for (let i = 1; i <= STEP_COUNT; ++i) {
171+
const docs = [];
172+
173+
for (let j = 0; j < documentsPerStep; ++j) {
174+
docs.push(doc(`collection/${j}`, ++version, { v: version }));
175+
}
176+
177+
const changeType = i === 1 ? 'added' : 'modified';
178+
179+
steps = steps
180+
.watchSends({ affects: [query] }, ...docs)
181+
.watchSnapshots(++version)
182+
.expectEvents(query, { [changeType]: docs });
183+
}
184+
185+
return steps;
186+
});
187+
188+
specTest('Watch has cached results', [], () => {
189+
const documentsPerStep = 100;
190+
let version = 1;
191+
192+
let steps = spec().withGCEnabled(false);
193+
194+
for (let i = 1; i <= STEP_COUNT; ++i) {
195+
const collPath = `collection/${i}/coll`;
196+
const query = Query.atPath(path(collPath)).addOrderBy(orderBy('v'));
197+
198+
const docs = [];
199+
for (let j = 0; j < documentsPerStep; ++j) {
200+
docs.push(doc(`${collPath}/${j}`, ++version, { v: j }));
201+
}
202+
203+
steps = steps
204+
.userListens(query)
205+
.watchAcksFull(query, ++version, ...docs)
206+
.expectEvents(query, { added: docs })
207+
.userUnlistens(query)
208+
.watchRemoves(query)
209+
.userListens(query, 'resume-token-' + version)
210+
.expectEvents(query, { added: docs, fromCache: true })
211+
.watchAcksFull(query, ++version)
212+
.expectEvents(query, {})
213+
.userUnlistens(query)
214+
.watchRemoves(query);
215+
}
216+
217+
return steps;
218+
});
219+
});

0 commit comments

Comments
 (0)