15
15
* limitations under the License.
16
16
*/
17
17
18
+ import { Unsubscribe } from '../api/reference_impl' ;
19
+
20
+ import {
21
+ setTestingHooksSpi ,
22
+ ExistenceFilterMismatchInfo ,
23
+ TestingHooksSpi
24
+ } from './testing_hooks_spi' ;
25
+
18
26
/**
19
- * Manages "testing hooks", hooks into the internals of the SDK to verify
20
- * internal state and events during integration tests. Do not use this class
21
- * except for testing purposes.
22
- *
23
- * There are two ways to retrieve the global singleton instance of this class:
24
- * 1. The `instance` property, which returns null if the global singleton
25
- * instance has not been created. Use this property if the caller should
26
- * "do nothing" if there are no testing hooks registered, such as when
27
- * delivering an event to notify registered callbacks.
28
- * 2. The `getOrCreateInstance()` method, which creates the global singleton
29
- * instance if it has not been created. Use this method if the instance is
30
- * needed to, for example, register a callback.
27
+ * Testing hooks for use by Firestore's integration test suite to reach into the
28
+ * SDK internals to validate logic and behavior that is not visible from the
29
+ * public API surface.
31
30
*
32
31
* @internal
33
32
*/
34
33
export class TestingHooks {
35
- private readonly onExistenceFilterMismatchCallbacks = new Map <
36
- Symbol ,
37
- ExistenceFilterMismatchCallback
38
- > ( ) ;
39
-
40
- private constructor ( ) { }
41
-
42
- /**
43
- * Returns the singleton instance of this class, or null if it has not been
44
- * initialized.
45
- */
46
- static get instance ( ) : TestingHooks | null {
47
- return gTestingHooksSingletonInstance ;
48
- }
49
-
50
- /**
51
- * Returns the singleton instance of this class, creating it if is has never
52
- * been created before.
53
- */
54
- static getOrCreateInstance ( ) : TestingHooks {
55
- if ( gTestingHooksSingletonInstance === null ) {
56
- gTestingHooksSingletonInstance = new TestingHooks ( ) ;
57
- }
58
- return gTestingHooksSingletonInstance ;
34
+ private constructor ( ) {
35
+ throw new Error ( 'instances of this class should not be created' ) ;
59
36
}
60
37
61
38
/**
@@ -72,87 +49,58 @@ export class TestingHooks {
72
49
* the first invocation of the returned function does anything; all subsequent
73
50
* invocations do nothing.
74
51
*/
75
- onExistenceFilterMismatch (
52
+ static onExistenceFilterMismatch (
76
53
callback : ExistenceFilterMismatchCallback
77
- ) : ( ) => void {
78
- const key = Symbol ( ) ;
79
- this . onExistenceFilterMismatchCallbacks . set ( key , callback ) ;
80
- return ( ) => this . onExistenceFilterMismatchCallbacks . delete ( key ) ;
81
- }
82
-
83
- /**
84
- * Invokes all currently-registered `onExistenceFilterMismatch` callbacks.
85
- * @param info Information about the existence filter mismatch.
86
- */
87
- notifyOnExistenceFilterMismatch ( info : ExistenceFilterMismatchInfo ) : void {
88
- this . onExistenceFilterMismatchCallbacks . forEach ( callback => callback ( info ) ) ;
54
+ ) : Unsubscribe {
55
+ return TestingHooksSpiImpl . instance . onExistenceFilterMismatch ( callback ) ;
89
56
}
90
57
}
91
58
92
59
/**
93
- * Information about an existence filter mismatch, as specified to callbacks
94
- * registered with `TestingUtils.onExistenceFilterMismatch()`.
60
+ * The signature of callbacks registered with
61
+ * `TestingUtils.onExistenceFilterMismatch()`.
62
+ *
63
+ * The return value, if any, is ignored.
64
+ *
65
+ * @internal
95
66
*/
96
- export interface ExistenceFilterMismatchInfo {
97
- /** The number of documents that matched the query in the local cache. */
98
- localCacheCount : number ;
99
-
100
- /**
101
- * The number of documents that matched the query on the server, as specified
102
- * in the ExistenceFilter message's `count` field.
103
- */
104
- existenceFilterCount : number ;
105
-
106
- /**
107
- * The projectId used when checking documents for membership in the bloom
108
- * filter.
109
- */
110
- projectId : string ;
111
-
112
- /**
113
- * The databaseId used when checking documents for membership in the bloom
114
- * filter.
115
- */
116
- databaseId : string ;
67
+ export type ExistenceFilterMismatchCallback = (
68
+ info : ExistenceFilterMismatchInfo
69
+ ) => unknown ;
117
70
118
- /**
119
- * Information about the bloom filter provided by Watch in the ExistenceFilter
120
- * message's `unchangedNames` field. If this property is omitted or undefined
121
- * then that means that Watch did _not_ provide a bloom filter.
122
- */
123
- bloomFilter ?: {
124
- /**
125
- * Whether a full requery was averted by using the bloom filter. If false,
126
- * then something happened, such as a false positive, to prevent using the
127
- * bloom filter to avoid a full requery.
128
- */
129
- applied : boolean ;
71
+ /**
72
+ * The implementation of `TestingHooksSpi`.
73
+ */
74
+ class TestingHooksSpiImpl implements TestingHooksSpi {
75
+ private readonly existenceFilterMismatchCallbacksById = new Map <
76
+ Symbol ,
77
+ ExistenceFilterMismatchCallback
78
+ > ( ) ;
130
79
131
- /** The number of hash functions used in the bloom filter. */
132
- hashCount : number ;
80
+ private constructor ( ) { }
133
81
134
- /** The number of bytes in the bloom filter's bitmask. */
135
- bitmapLength : number ;
82
+ static get instance ( ) : TestingHooksSpiImpl {
83
+ if ( ! testingHooksSpiImplInstance ) {
84
+ testingHooksSpiImplInstance = new TestingHooksSpiImpl ( ) ;
85
+ setTestingHooksSpi ( testingHooksSpiImplInstance ) ;
86
+ }
87
+ return testingHooksSpiImplInstance ;
88
+ }
136
89
137
- /** The number of bits of padding in the last byte of the bloom filter. */
138
- padding : number ;
90
+ notifyOnExistenceFilterMismatch ( info : ExistenceFilterMismatchInfo ) : void {
91
+ this . existenceFilterMismatchCallbacksById . forEach ( callback =>
92
+ callback ( info )
93
+ ) ;
94
+ }
139
95
140
- /**
141
- * Tests the given string for membership in the bloom filter created from
142
- * the existence filter; will be undefined if creating the bloom filter
143
- * failed.
144
- */
145
- mightContain ?: ( value : string ) => boolean ;
146
- } ;
96
+ onExistenceFilterMismatch (
97
+ callback : ExistenceFilterMismatchCallback
98
+ ) : Unsubscribe {
99
+ const id = Symbol ( ) ;
100
+ const callbacks = this . existenceFilterMismatchCallbacksById ;
101
+ callbacks . set ( id , callback ) ;
102
+ return ( ) => callbacks . delete ( id ) ;
103
+ }
147
104
}
148
105
149
- /**
150
- * The signature of callbacks registered with
151
- * `TestingUtils.onExistenceFilterMismatch()`.
152
- */
153
- export type ExistenceFilterMismatchCallback = (
154
- info : ExistenceFilterMismatchInfo
155
- ) => void ;
156
-
157
- /** The global singleton instance of `TestingHooks`. */
158
- let gTestingHooksSingletonInstance : TestingHooks | null = null ;
106
+ let testingHooksSpiImplInstance : TestingHooksSpiImpl | null = null ;
0 commit comments