Fixed bug causing pending events of non-sandy plugins not to be part of the export

Summary:
During testing I noticed that even though plugin queues were flushed, the processed messages didn't end up in the export snapshots. This was caused by holding a ref of an older snapshot of the state

Changelog: Fixed an issue where data that arrived in the background was not part of the generated Flipper export.

Reviewed By: nikoant

Differential Revision: D26250897

fbshipit-source-id: ddd3f5bb19e38a1b13498d03f235bf63858eb8f8
This commit is contained in:
Michel Weststrate
2021-02-09 04:12:09 -08:00
committed by Facebook GitHub Bot
parent 2df117923c
commit 7650ab620d
2 changed files with 81 additions and 5 deletions

View File

@@ -1095,6 +1095,7 @@ const sandyTestPlugin = new _SandyPluginDefinition(
}); });
}); });
return { return {
counter,
enableCustomExport() { enableCustomExport() {
client.onExport(async (idler, onStatus) => { client.onExport(async (idler, onStatus) => {
if (idler.shouldIdle()) { if (idler.shouldIdle()) {
@@ -1116,15 +1117,19 @@ const sandyTestPlugin = new _SandyPluginDefinition(
); );
test('Sandy plugins are exported properly', async () => { test('Sandy plugins are exported properly', async () => {
const {client, sendMessage, store} = await createMockFlipperWithPlugin( const {
sandyTestPlugin, client,
); sendMessage,
store,
device,
} = await createMockFlipperWithPlugin(sandyTestPlugin);
// We do select another plugin, to verify that pending message queues are indeed processed before exporting // We do select another plugin, to verify that pending message queues are indeed processed before exporting
store.dispatch( store.dispatch(
selectPlugin({ selectPlugin({
selectedPlugin: 'DeviceLogs', selectedPlugin: 'DeviceLogs',
selectedApp: client.id, selectedApp: null,
selectedDevice: device,
deepLinkPayload: null, deepLinkPayload: null,
}), }),
); );
@@ -1134,7 +1139,16 @@ test('Sandy plugins are exported properly', async () => {
sendMessage('inc', {}); sendMessage('inc', {});
sendMessage('inc', {}); sendMessage('inc', {});
// not flushed
expect(
client.sandyPluginStates.get(sandyTestPlugin.id)!.instanceApi.counter.get(),
).toBe(0);
const storeExport = await exportStore(store); const storeExport = await exportStore(store);
expect(
client.sandyPluginStates.get(sandyTestPlugin.id)!.instanceApi.counter.get(),
).toBe(3);
const serial = storeExport.exportStoreData.device!.serial; const serial = storeExport.exportStoreData.device!.serial;
expect(serial).not.toBeFalsy(); expect(serial).not.toBeFalsy();
expect(storeExport.exportStoreData.pluginStates2).toEqual({ expect(storeExport.exportStoreData.pluginStates2).toEqual({
@@ -1144,6 +1158,67 @@ test('Sandy plugins are exported properly', async () => {
}); });
}); });
test('Non sandy plugins are exported properly if they are still queued', async () => {
type State = {
counter: number;
};
const {sendMessage, store, device} = await createMockFlipperWithPlugin(
class TestPlugin extends FlipperPlugin<any, any, State> {
static id = 'TestPlugin';
static defaultPersistedState: State = {
counter: 0,
};
static persistedStateReducer(p: State, method: string): State {
if (method === 'inc') {
return {
counter: p.counter + 1,
};
}
return p;
}
} as any,
);
// We do select another plugin, to verify that pending message queues are indeed processed before exporting
store.dispatch(
selectPlugin({
selectedPlugin: 'DeviceLogs',
selectedApp: null,
selectedDevice: device,
deepLinkPayload: null,
}),
);
// Deliberately not using 'act' here, to verify that exportStore itself makes sure buffers are flushed first
sendMessage('inc', {});
sendMessage('inc', {});
sendMessage('inc', {});
// not flushed
expect(store.getState().pluginStates).toMatchInlineSnapshot(`Object {}`);
const storeExport = await exportStore(store);
// flushed
expect(store.getState().pluginStates).toMatchInlineSnapshot(`
Object {
"TestApp#Android#MockAndroidDevice#serial#TestPlugin": Object {
"counter": 3,
},
}
`);
const serial = storeExport.exportStoreData.device!.serial;
expect(serial).not.toBeFalsy();
expect(storeExport.exportStoreData.store.pluginStates).toMatchInlineSnapshot(`
Object {
"TestApp#Android#MockAndroidDevice#${serial}#TestPlugin": "{\\"counter\\":3}",
}
`);
});
test('Sandy plugins with custom export are exported properly', async () => { test('Sandy plugins with custom export are exported properly', async () => {
const {client, sendMessage, store} = await createMockFlipperWithPlugin( const {client, sendMessage, store} = await createMockFlipperWithPlugin(
sandyTestPlugin, sandyTestPlugin,

View File

@@ -652,7 +652,7 @@ async function getStoreExport(
exportData: ExportType; exportData: ExportType;
fetchMetaDataErrors: {[plugin: string]: Error} | null; fetchMetaDataErrors: {[plugin: string]: Error} | null;
}> { }> {
const state = store.getState(); let state = store.getState();
const {clients, selectedApp, selectedDevice} = state.connections; const {clients, selectedApp, selectedDevice} = state.connections;
const pluginsToProcess = determinePluginsToProcess( const pluginsToProcess = determinePluginsToProcess(
clients, clients,
@@ -662,6 +662,7 @@ async function getStoreExport(
statusUpdate?.('Preparing to process data queues for plugins...'); statusUpdate?.('Preparing to process data queues for plugins...');
await processQueues(store, pluginsToProcess, statusUpdate, idler); await processQueues(store, pluginsToProcess, statusUpdate, idler);
state = store.getState();
statusUpdate && statusUpdate('Preparing to fetch metadata from client...'); statusUpdate && statusUpdate('Preparing to fetch metadata from client...');
const fetchMetaDataMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:fetch-meta-data`; const fetchMetaDataMarker = `${EXPORT_FLIPPER_TRACE_EVENT}:fetch-meta-data`;