Skip to content

Commit 7345943

Browse files
committed
tests: fix various test issues caused by version upgrades
1 parent 447a1bf commit 7345943

File tree

6 files changed

+91
-24
lines changed

6 files changed

+91
-24
lines changed

test/exponential-retry.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import * as sinon from 'sinon';
1818

1919
import {ExponentialRetry} from '../src/exponential-retry';
2020
import {Duration} from '../src/temporal';
21+
import {TestUtils} from './test-utils';
2122

2223
// eslint-disable-next-line @typescript-eslint/no-explicit-any
2324
function introspect(obj: unknown): any {
@@ -52,27 +53,30 @@ describe('exponential retry class', () => {
5253
});
5354

5455
it('makes the first callback', () => {
55-
const clock = sandbox.useFakeTimers();
56+
const clock = TestUtils.useFakeTimers(sandbox);
5657
const er = new ExponentialRetry<TestItem>(
5758
Duration.from({millis: 100}),
5859
Duration.from({millis: 1000}),
5960
);
6061
sandbox.stub(global.Math, 'random').returns(0.75);
6162

6263
const item = makeItem();
64+
let retried = false;
6365
er.retryLater(item, (s: typeof item, t: Duration) => {
6466
assert.strictEqual(s, item);
6567
assert.strictEqual(t.totalOf('millisecond'), 125);
68+
retried = true;
6669
});
6770

6871
clock.tick(125);
6972

7073
const leftovers = er.close();
74+
assert.strictEqual(retried, true);
7175
assert.strictEqual(leftovers.length, 0);
7276
});
7377

7478
it('closes gracefully', () => {
75-
const clock = sandbox.useFakeTimers();
79+
const clock = TestUtils.useFakeTimers(sandbox);
7680
const er = new ExponentialRetry<TestItem>(
7781
Duration.from({millis: 100}),
7882
Duration.from({millis: 1000}),
@@ -102,7 +106,7 @@ describe('exponential retry class', () => {
102106
});
103107

104108
it('backs off exponentially', () => {
105-
const clock = sandbox.useFakeTimers();
109+
const clock = TestUtils.useFakeTimers(sandbox);
106110
const er = new ExponentialRetry<TestItem>(
107111
Duration.from({millis: 100}),
108112
Duration.from({millis: 1000}),
@@ -136,7 +140,7 @@ describe('exponential retry class', () => {
136140
});
137141

138142
it('backs off exponentially until the max backoff', () => {
139-
const clock = sandbox.useFakeTimers();
143+
const clock = TestUtils.useFakeTimers(sandbox);
140144
const item = makeItem();
141145
const er = new ExponentialRetry<TestItem>(
142146
Duration.from({millis: 100}),
@@ -170,7 +174,7 @@ describe('exponential retry class', () => {
170174
});
171175

172176
it('calls retries in the right order', () => {
173-
const clock = sandbox.useFakeTimers();
177+
const clock = TestUtils.useFakeTimers(sandbox);
174178
const items = [makeItem(), makeItem()];
175179

176180
const er = new ExponentialRetry<TestItem>(

test/lease-manager.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import {
3030
Subscriber,
3131
} from '../src/subscriber';
3232
import {defaultOptions} from '../src/default-options';
33+
import {TestUtils} from './test-utils';
3334

3435
const FREE_MEM = 9376387072;
3536
const fakeos = {
@@ -237,7 +238,7 @@ describe('LeaseManager', () => {
237238
// This random number was generated once to keep the test results stable.
238239
random = 0.5756015072052962;
239240
sandbox.stub(global.Math, 'random').returns(random);
240-
clock = sandbox.useFakeTimers();
241+
clock = TestUtils.useFakeTimers(sandbox);
241242
expectedTimeout =
242243
(subscriber.ackDeadline * 1000 * 0.9 - subscriber.modAckLatency) *
243244
random;
@@ -397,7 +398,7 @@ describe('LeaseManager', () => {
397398
});
398399

399400
it('should cancel any lease extensions', () => {
400-
const clock = sandbox.useFakeTimers();
401+
const clock = TestUtils.useFakeTimers(sandbox);
401402
const stub = sandbox.stub(subscriber, 'modAck').resolves();
402403

403404
leaseManager.add(new FakeMessage() as {} as Message);
@@ -518,7 +519,7 @@ describe('LeaseManager', () => {
518519
});
519520

520521
it('should cancel any extensions if no messages are left', () => {
521-
const clock = sandbox.useFakeTimers();
522+
const clock = TestUtils.useFakeTimers(sandbox);
522523
const message = new FakeMessage() as {} as Message;
523524
const stub = sandbox.stub(subscriber, 'modAck').resolves();
524525

@@ -563,7 +564,7 @@ describe('LeaseManager', () => {
563564

564565
describe('deadline extension', () => {
565566
beforeEach(() => {
566-
sandbox.useFakeTimers();
567+
TestUtils.useFakeTimers(sandbox);
567568
});
568569
afterEach(() => {
569570
sandbox.clock.restore();

test/message-queues.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import * as messageTypes from '../src/message-queues';
2626
import {BatchError} from '../src/message-queues';
2727
import {Message, Subscriber} from '../src/subscriber';
2828
import {DebugMessage} from '../src/debug';
29+
import {TestUtils} from './test-utils';
2930

3031
class FakeClient {
3132
async acknowledge(
@@ -170,7 +171,7 @@ describe('MessageQueues', () => {
170171
});
171172

172173
it('should schedule a flush if needed', () => {
173-
const clock = sandbox.useFakeTimers();
174+
const clock = TestUtils.useFakeTimers(sandbox);
174175
const stub = sandbox.stub(messageQueue, 'flush');
175176
const delay = 1000;
176177

@@ -183,7 +184,7 @@ describe('MessageQueues', () => {
183184
});
184185

185186
it('should return a Promise that resolves when the ack is sent', async () => {
186-
const clock = sandbox.useFakeTimers();
187+
const clock = TestUtils.useFakeTimers(sandbox);
187188
const delay = 1000;
188189
messageQueue.setOptions({maxMilliseconds: delay});
189190

@@ -204,7 +205,7 @@ describe('MessageQueues', () => {
204205

205206
describe('flush', () => {
206207
it('should cancel scheduled flushes', () => {
207-
const clock = sandbox.useFakeTimers();
208+
const clock = TestUtils.useFakeTimers(sandbox);
208209
const spy = sandbox.spy(messageQueue, 'flush');
209210
const delay = 1000;
210211

@@ -350,7 +351,7 @@ describe('MessageQueues', () => {
350351
});
351352

352353
it('should default maxMilliseconds to 100', () => {
353-
const clock = sandbox.useFakeTimers();
354+
const clock = TestUtils.useFakeTimers(sandbox);
354355
const stub = sandbox.stub(messageQueue, 'flush');
355356

356357
void messageQueue.add(fakeMessage());
@@ -360,7 +361,7 @@ describe('MessageQueues', () => {
360361
});
361362

362363
it('should respect user supplied maxMilliseconds', () => {
363-
const clock = sandbox.useFakeTimers();
364+
const clock = TestUtils.useFakeTimers(sandbox);
364365
const stub = sandbox.stub(messageQueue, 'flush');
365366
const maxMilliseconds = 10000;
366367

@@ -557,7 +558,7 @@ describe('MessageQueues', () => {
557558
// This doesn't need to be duplicated down to modAck because it's just
558559
// testing common code.
559560
it('should retry transient failures', async () => {
560-
const clock = sandbox.useFakeTimers();
561+
const clock = TestUtils.useFakeTimers(sandbox);
561562
sandbox.stub(global.Math, 'random').returns(0.5);
562563

563564
const message = fakeMessage();

test/message-stream.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ import * as sinon from 'sinon';
2222
import {Duplex, PassThrough} from 'stream';
2323
import * as uuid from 'uuid';
2424
import * as defer from 'p-defer';
25+
import {promisify} from 'util';
2526

2627
import * as messageTypes from '../src/message-stream';
2728
import {Subscriber} from '../src/subscriber';
2829
import {defaultOptions} from '../src/default-options';
2930
import {Duration} from '../src/temporal';
30-
import {promisify} from 'util';
31+
import {TestUtils} from './test-utils';
3132

3233
const FAKE_STREAMING_PULL_TIMEOUT = 123456789;
3334
const FAKE_CLIENT_CONFIG = {
@@ -63,13 +64,21 @@ class FakePassThrough extends PassThrough {
6364
}
6465
}
6566

67+
interface AccessReadableState {
68+
_readableState: StreamState;
69+
}
70+
6671
class FakeGrpcStream extends Duplex {
6772
options: StreamingPullOptions;
68-
_readableState!: StreamState;
6973
constructor(options: StreamingPullOptions) {
7074
super({objectMode: true});
7175
this.options = options;
7276
}
77+
78+
get readableState(): StreamState {
79+
return (this as unknown as AccessReadableState)._readableState;
80+
}
81+
7382
cancel(): void {
7483
const status = {
7584
code: 1,
@@ -156,8 +165,8 @@ describe('MessageStream', () => {
156165
});
157166

158167
beforeEach(async () => {
159-
sandbox.useFakeTimers();
160168
now = Date.now();
169+
TestUtils.useFakeTimers(sandbox, now);
161170

162171
const gaxClient = new FakeGaxClient();
163172
client = gaxClient.client; // we hit the grpc client directly
@@ -207,7 +216,7 @@ describe('MessageStream', () => {
207216
describe('defaults', () => {
208217
it('should default highWaterMark to 0', () => {
209218
client.streams.forEach(stream => {
210-
assert.strictEqual(stream._readableState.highWaterMark, 0);
219+
assert.strictEqual(stream.readableState.highWaterMark, 0);
211220
});
212221
});
213222

@@ -229,7 +238,10 @@ describe('MessageStream', () => {
229238

230239
it('should default timeout to 5 minutes', () => {
231240
const expectedTimeout = now + 60000 * 5;
232-
assert.strictEqual(client.deadline, expectedTimeout);
241+
242+
// Floating point calcuations in Duration might make this a few
243+
// microseconds off.
244+
assert.ok(Math.abs(client.deadline! - expectedTimeout) < 10);
233245
});
234246
});
235247

@@ -252,9 +264,10 @@ describe('MessageStream', () => {
252264
client.streams.length,
253265
defaultOptions.subscription.maxStreams,
254266
);
267+
255268
client.streams.forEach(stream => {
256269
assert.strictEqual(
257-
stream._readableState.highWaterMark,
270+
stream.readableState.highWaterMark,
258271
highWaterMark,
259272
);
260273
});

test/publisher/message-queues.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import * as p from '../../src/publisher';
2626
import * as b from '../../src/publisher/message-batch';
2727
import * as q from '../../src/publisher/message-queues';
2828
import {PublishError} from '../../src/publisher/publish-error';
29+
import {TestUtils} from '../test-utils';
2930

3031
class FakeTopic {
3132
name = 'projects/foo/topics/fake-topic';
@@ -279,7 +280,7 @@ describe('Message Queues', () => {
279280
});
280281

281282
it('should set a timeout to publish if need be', () => {
282-
const clock = sandbox.useFakeTimers();
283+
const clock = TestUtils.useFakeTimers(sandbox);
283284
const stub = sandbox.stub(queue, 'publish').resolves();
284285
const maxMilliseconds = 1234;
285286

@@ -293,7 +294,7 @@ describe('Message Queues', () => {
293294
});
294295

295296
it('should noop if a timeout is already set', () => {
296-
const clock = sandbox.useFakeTimers();
297+
const clock = TestUtils.useFakeTimers(sandbox);
297298
const stub = sandbox.stub(queue, 'publish').resolves();
298299
const maxMilliseconds = 1234;
299300

@@ -582,7 +583,7 @@ describe('Message Queues', () => {
582583

583584
beforeEach(() => {
584585
queue.batchOptions = {maxMilliseconds};
585-
clock = sinon.useFakeTimers();
586+
clock = TestUtils.useFakeTimers(sandbox);
586587
});
587588

588589
afterEach(() => {

test/test-utils.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import {SinonSandbox, SinonFakeTimers} from 'sinon';
16+
17+
type FakeTimersParam = Parameters<SinonSandbox['useFakeTimers']>[0];
18+
interface FakeTimerConfig {
19+
now?: number,
20+
toFake?: string[];
21+
}
22+
23+
/**
24+
* Utilities for unit test code.
25+
*
26+
* @private
27+
*/
28+
export class TestUtils {
29+
/**
30+
* This helper should be used to enable fake timers for Sinon sandbox.
31+
*
32+
* @param sandbox The sandbox
33+
* @param now An optional date to set for "now"
34+
* @returns The clock object from useFakeTimers()
35+
*/
36+
static useFakeTimers(sandbox: SinonSandbox, now?: number): SinonFakeTimers {
37+
const config: FakeTimerConfig = {
38+
toFake: ['setTimeout', 'clearTimeout', 'setInterval', 'clearInterval', 'Date'],
39+
};
40+
if (now) {
41+
config.now = now;
42+
}
43+
44+
// The types are screwy in useFakeTimers(). I'm just going to pick one.
45+
return sandbox.useFakeTimers(config as FakeTimersParam);
46+
}
47+
}

0 commit comments

Comments
 (0)