Skip to content

Commit dca8d99

Browse files
committed
add golden test files
1 parent 5abbe86 commit dca8d99

File tree

27 files changed

+82
-1354
lines changed

27 files changed

+82
-1354
lines changed

packages/firestore/src/remote/bloom_filter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ export class BloomFilter {
2626
padding: number,
2727
private readonly hashCount: number
2828
) {
29-
debugAssert(padding >= 0, 'Padding is negative.');
29+
debugAssert(padding >= 0, 'Padding is negative or undefined.');
3030
this.bitSize = this.bitmap.length * 8 - padding;
3131
debugAssert(this.bitSize >= 0, 'Bitmap size is negative.');
32-
debugAssert(this.hashCount >= 0, 'Hash count is negative.');
32+
debugAssert(this.hashCount >= 0, 'Hash count is negative or undefined.');
3333
}
3434

3535
getBitSize(): number {

packages/firestore/test/unit/remote/bloom_filter.test.ts

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17+
import { readFileSync, readdirSync } from 'fs';
18+
import { parse, resolve } from 'path';
19+
1720
import { expect } from 'chai';
1821

1922
import { BloomFilter } from '../../../src/remote/bloom_filter';
2023

21-
import testData from './bloom_filter_test_data.json';
22-
2324
describe('BloomFilter', () => {
2425
it('can initiate an empty BloomFilter', () => {
2526
const bloomFilter = new BloomFilter(
@@ -95,35 +96,63 @@ describe('BloomFilter', () => {
9596
expect(nonEmptyBloomFilter.mightContain('')).to.be.false;
9697
});
9798

99+
/**
100+
* Golden tests are generated by backend based on inserting n number of
101+
* documents path into Bloom filter.
102+
*
103+
* Full documents path is generated by concating documentPrefix and n, ie,
104+
* projects/project-1/databases/database-1/documents/coll/doc11
105+
*
106+
* The test result is generated by checking the membership of documents from
107+
* documentPrefix+0 to documentPrefix+2n. The membership results from 0 to n
108+
* is expected to be 1, and from n to 2n to be 0 with some false positive results.
109+
*
110+
* The test result of BloomFilter.mightContain() should match the backend result
111+
* exactly.
112+
*/
98113
describe('BloomFilter membership test', () => {
99-
const prefix = 'projects/project-1/databases/database-1/documents/coll/doc';
114+
const documentPrefix =
115+
'projects/project-1/databases/database-1/documents/coll/doc';
116+
const testDataFolder = 'test/unit/remote/bloom_filter_golden_test_data';
100117

101118
interface TestDataType {
102-
// Bloom filter result created by backend based on documents: prefix+(0 ~i)
103119
bits: {
104-
bitmap: number[];
120+
bitmap: string;
105121
padding: number;
106122
};
107123
hashCount: number;
108-
// Check membership of documents prefix+(0 ~2i)
109-
membershipCheckCount: number;
110-
// Membership result on docs from 0~i are always postive, i~2i might have false positive
111-
membershipTestResult: string;
124+
}
125+
126+
function convertBase64ToUint8Array(base64: string = ''): Uint8Array {
127+
return Uint8Array.from(atob(base64), item => item.charCodeAt(0));
112128
}
113129

114130
it('mightContain result should match backend result', () => {
115-
testData.forEach((data: TestDataType) => {
116-
const { bits, hashCount, membershipCheckCount, membershipTestResult } =
117-
data;
118-
const bloomFilter = new BloomFilter(
119-
Uint8Array.from(bits.bitmap),
120-
bits.padding,
121-
hashCount
122-
);
123-
for (let i = 0; i < membershipCheckCount; i++) {
124-
const isMember = membershipTestResult[i] === '1' ? true : false;
125-
const mightContain = bloomFilter.mightContain(prefix + i);
126-
expect(mightContain).to.equal(isMember);
131+
readdirSync(testDataFolder).forEach(filename => {
132+
const ext = parse(filename).ext;
133+
134+
if (ext === '.json') {
135+
const testDataPath = resolve(testDataFolder, filename);
136+
const testResultPath = testDataPath.replace(
137+
'bloom_filter_proto.json',
138+
'membership_test_result.txt'
139+
);
140+
const testData: TestDataType = JSON.parse(
141+
readFileSync(testDataPath, 'utf8')
142+
);
143+
const testResult: string = readFileSync(testResultPath, 'utf8');
144+
const { bits = { bitmap: '', padding: 0 }, hashCount = 0 } = testData;
145+
const bloomFilter = new BloomFilter(
146+
convertBase64ToUint8Array(bits.bitmap),
147+
bits.padding || 0,
148+
hashCount || 0
149+
);
150+
for (let i = 0; i < testResult.length; i++) {
151+
const backendMembershipResult =
152+
testResult[i] === '1' ? true : false;
153+
const mightContain = bloomFilter.mightContain(documentPrefix + i);
154+
expect(mightContain).to.equal(backendMembershipResult);
155+
}
127156
}
128157
});
129158
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{ "bits": { "bitmap": "RswZ", "padding": 1 }, "hashCount": 16 }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"bits":{"bitmap":"mwE=","padding":5},"hashCount":8}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"bits":{}}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
00

packages/firestore/test/unit/remote/bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_0001_bloom_filter_proto.json

Lines changed: 7 additions & 0 deletions
Large diffs are not rendered by default.

packages/firestore/test/unit/remote/bloom_filter_golden_test_data/Validation_BloomFilterTest_MD5_50000_0001_membership_test_result.txt

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)