@datadog/mobile-react-native
Version:
A client-side React Native module to interact with Datadog
203 lines (171 loc) • 7.84 kB
text/typescript
/*
* Unless explicitly stated otherwise all files in this repository are licensed under the Apache License Version 2.0.
* This product includes software developed at Datadog (https://www.datadoghq.com/).
* Copyright 2016-Present Datadog, Inc.
*/
import { InternalLog } from '../../../../InternalLog';
import { DdSdk } from '../../../DdSdk';
import { BoundedBuffer } from '../BoundedBuffer';
describe('BoundedBuffer', () => {
beforeEach(() => {
jest.clearAllMocks();
});
describe('void callbacks', () => {
it('adds void callbacks then drains them', async () => {
const buffer = new BoundedBuffer();
const fakeCallback = jest.fn();
buffer.addCallback(fakeCallback);
await buffer.drain();
expect(fakeCallback).toHaveBeenCalledTimes(1);
await buffer.drain();
expect(fakeCallback).toHaveBeenCalledTimes(1);
});
});
describe('callbacks with ids', () => {
it('links the callbacks to pass the returned id from first callback', async () => {
const buffer = new BoundedBuffer();
const callbackReturningId = jest
.fn()
.mockReturnValueOnce('callbackId');
const callbackWithId = jest.fn();
const bufferId = await buffer.addCallbackReturningId(
callbackReturningId
);
buffer.addCallbackWithId(callbackWithId, bufferId);
await buffer.drain();
expect(callbackReturningId).toHaveBeenCalledTimes(1);
expect(callbackWithId).toHaveBeenCalledTimes(1);
expect(callbackWithId).toHaveBeenCalledWith('callbackId');
});
it('links the correct the returned id when multiple callbacks are registered', async () => {
const buffer = new BoundedBuffer();
const callbackReturningId = jest
.fn()
.mockReturnValueOnce('callbackId1')
.mockReturnValueOnce('callbackId2');
const callbackWithId = jest.fn();
const bufferId1 = await buffer.addCallbackReturningId(
callbackReturningId
);
const bufferId2 = await buffer.addCallbackReturningId(
callbackReturningId
);
buffer.addCallbackWithId(callbackWithId, bufferId1);
buffer.addCallbackWithId(callbackWithId, bufferId2);
await buffer.drain();
expect(callbackWithId).toHaveBeenCalledTimes(2);
expect(callbackWithId).toHaveBeenNthCalledWith(1, 'callbackId1');
expect(callbackWithId).toHaveBeenNthCalledWith(2, 'callbackId2');
});
it('does not run the linked callback when the callback returning id fails', async () => {
const buffer = new BoundedBuffer();
const logSpy = jest.spyOn(InternalLog, 'log');
const callbackReturningId = jest.fn().mockImplementationOnce(() => {
throw new Error('issue running callback');
});
const callbackWithId = jest.fn();
const bufferId = await buffer.addCallbackReturningId(
callbackReturningId
);
buffer.addCallbackWithId(callbackWithId, bufferId);
await buffer.drain();
expect(callbackWithId).not.toHaveBeenCalled();
expect(logSpy).toHaveBeenCalledWith(
'Error running a callback returning an id in Buffer: Error: issue running callback',
'warn'
);
expect(logSpy).toHaveBeenCalledWith(
'1 event was not sent as callback id was not set',
'warn'
);
});
it('does not crash when Math.random is mocked', async () => {
const spy = jest.spyOn(Math, 'random').mockReturnValue(42);
const buffer = new BoundedBuffer();
const callbackReturningId = jest
.fn()
.mockReturnValueOnce('callbackId1')
.mockReturnValueOnce('callbackId2')
.mockReturnValueOnce('callbackId3');
const callbackWithId = jest.fn();
const bufferId1 = await buffer.addCallbackReturningId(
callbackReturningId
);
const bufferId2 = await buffer.addCallbackReturningId(
callbackReturningId
);
const bufferId3 = await buffer.addCallbackReturningId(
callbackReturningId
);
spy.mockRestore();
buffer.addCallbackWithId(callbackWithId, bufferId1);
buffer.addCallbackWithId(callbackWithId, bufferId2);
buffer.addCallbackWithId(callbackWithId, bufferId3);
await buffer.drain();
expect(callbackWithId).toHaveBeenCalledTimes(1);
expect(callbackWithId).toHaveBeenNthCalledWith(1, 'callbackId1');
expect(DdSdk.telemetryError).toHaveBeenCalledWith(
'Could not generate enough random numbers happened 2 times.',
'',
'RandomIdGenerationError'
);
});
});
describe('buffer size', () => {
it('does not add any new void callback when the limit size is reached', async () => {
const buffer = new BoundedBuffer(3);
const fakeCallback = jest.fn();
buffer.addCallback(fakeCallback);
buffer.addCallback(fakeCallback);
buffer.addCallback(fakeCallback);
buffer.addCallback(fakeCallback);
await buffer.drain();
expect(fakeCallback).toHaveBeenCalledTimes(3);
expect(DdSdk.telemetryError).toHaveBeenCalledWith(
'Buffer overflow happened 1 times.',
'',
'BufferOverflow'
);
});
it('does not add any new callback with id when the limit size is reached', async () => {
const buffer = new BoundedBuffer(1);
const fakeCallback = jest.fn();
const callbackReturningId = jest
.fn()
.mockReturnValueOnce('callbackId');
const callbackWithId = jest.fn();
buffer.addCallback(fakeCallback);
const bufferId = await buffer.addCallbackReturningId(
callbackReturningId
);
buffer.addCallbackWithId(callbackWithId, bufferId);
await buffer.drain();
expect(fakeCallback).toHaveBeenCalledTimes(1);
expect(callbackReturningId).not.toHaveBeenCalled();
expect(callbackWithId).not.toHaveBeenCalled();
expect(DdSdk.telemetryError).toHaveBeenCalledWith(
'Buffer overflow happened 2 times.',
'',
'BufferOverflow'
);
});
it('adds corresponding callback with id even if the limit size is reached when corresponding callback exists', async () => {
const buffer = new BoundedBuffer(2);
const fakeCallback = jest.fn();
const callbackReturningId = jest
.fn()
.mockReturnValueOnce('callbackId');
const callbackWithId = jest.fn();
buffer.addCallback(fakeCallback);
const bufferId = await buffer.addCallbackReturningId(
callbackReturningId
);
buffer.addCallbackWithId(callbackWithId, bufferId);
await buffer.drain();
expect(fakeCallback).toHaveBeenCalledTimes(1);
expect(callbackReturningId).toHaveBeenCalledTimes(1);
expect(callbackWithId).toHaveBeenCalledTimes(1);
expect(DdSdk.telemetryError).not.toHaveBeenCalled();
});
});
});