From 05a7451173f4b35146d584c2e7597cc82f7138eb Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Thu, 4 Mar 2021 05:59:40 -0800 Subject: [PATCH] Killed pluginStateRecorder Summary: The state recorder was never updated for Sandy, nor is that really needed since Sandy offers better testing abstractions, and this was a stop gap with potential privacy concerns (due to recording real data). The feature didn't result in any actual test cases, so it seems we won't be missing out with this :) Reviewed By: passy Differential Revision: D26813798 fbshipit-source-id: 48ec11516fbc1a47a349a5799713ad05a7e1c73a --- desktop/app/src/init.tsx | 2 - desktop/app/src/utils/messageQueue.tsx | 15 +- desktop/app/src/utils/pluginStateRecorder.tsx | 216 ------------------ 3 files changed, 2 insertions(+), 231 deletions(-) delete mode 100644 desktop/app/src/utils/pluginStateRecorder.tsx diff --git a/desktop/app/src/init.tsx b/desktop/app/src/init.tsx index a7bd2fea4..bc0549f40 100644 --- a/desktop/app/src/init.tsx +++ b/desktop/app/src/init.tsx @@ -25,7 +25,6 @@ import {setPersistor} from './utils/persistor'; import React from 'react'; import path from 'path'; import {store} from './store'; -import {registerRecordingHooks} from './utils/pluginStateRecorder'; import {cache} from '@emotion/css'; import {CacheProvider} from '@emotion/react'; import {enableMapSet} from 'immer'; @@ -196,7 +195,6 @@ function init() { document.getElementById('root'), ); initLauncherHooks(config(), store); - registerRecordingHooks(store); enableConsoleHook(); window.flipperGlobalStoreDispatch = store.dispatch; diff --git a/desktop/app/src/utils/messageQueue.tsx b/desktop/app/src/utils/messageQueue.tsx index 4ca56e1c4..bc03b176e 100644 --- a/desktop/app/src/utils/messageQueue.tsx +++ b/desktop/app/src/utils/messageQueue.tsx @@ -10,10 +10,6 @@ import {PersistedStateReducer, FlipperDevicePlugin} from '../plugin'; import {State, MiddlewareAPI} from '../reducers/index'; import {setPluginState} from '../reducers/pluginStates'; -import { - flipperRecorderAddEvent, - isRecordingEvents, -} from './pluginStateRecorder'; import { clearMessageQueue, queueMessages, @@ -37,7 +33,6 @@ function processMessageClassic( message: Message, ): State { const reducerStartTime = Date.now(); - flipperRecorderAddEvent(pluginKey, message.method, message.params); try { const newPluginState = plugin.persistedStateReducer!( state, @@ -53,16 +48,10 @@ function processMessageClassic( } function processMessagesSandy( - pluginKey: string, plugin: _SandyPluginInstance, messages: Message[], ) { const reducerStartTime = Date.now(); - if (isRecordingEvents(pluginKey)) { - messages.forEach((message) => { - flipperRecorderAddEvent(pluginKey, message.method, message.params); - }); - } try { plugin.receiveMessages(messages); addBackgroundStat(plugin.definition.id, Date.now() - reducerStartTime); @@ -87,7 +76,7 @@ export function processMessagesImmediately( messages: Message[], ) { if (plugin instanceof _SandyPluginInstance) { - processMessagesSandy(pluginKey, plugin, messages); + processMessagesSandy(plugin, messages); } else { const persistedState = getCurrentPluginState(store, plugin, pluginKey); const newPluginState = messages.reduce( @@ -192,7 +181,7 @@ export async function processMessageQueue( do { if (_SandyPluginInstance.is(plugin)) { // Optimization: we could send a batch of messages here - processMessagesSandy(pluginKey, plugin, [messages[offset]]); + processMessagesSandy(plugin, [messages[offset]]); } else { newPluginState = processMessageClassic( newPluginState, diff --git a/desktop/app/src/utils/pluginStateRecorder.tsx b/desktop/app/src/utils/pluginStateRecorder.tsx deleted file mode 100644 index e692cb477..000000000 --- a/desktop/app/src/utils/pluginStateRecorder.tsx +++ /dev/null @@ -1,216 +0,0 @@ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -import path from 'path'; -import fs from 'fs'; -import {Store, State} from '../reducers'; -import {getPluginKey} from './pluginUtils'; -import {serialize} from './serialization'; -import {isSandyPlugin} from '../plugin'; - -let pluginRecordingState: { - recording: string; - pluginName: string; - startState: any; - events: [string, any][]; - endState: any; -} = initialRecordingState(); - -function initialRecordingState(): typeof pluginRecordingState { - return { - recording: '', - startState: undefined, - events: [], - endState: undefined, - pluginName: '', - }; -} - -export function isRecordingEvents(pluginKey: string) { - return pluginRecordingState.recording === pluginKey; -} - -export function flipperRecorderAddEvent( - pluginKey: string, - method: string, - params: any, -) { - if (pluginRecordingState.recording === pluginKey) { - pluginRecordingState.events.push([method, params]); - } -} - -async function flipperStartPluginRecording(state: State) { - if (pluginRecordingState.recording) { - throw new Error('A plugin recording is already running'); - } - const app = state.connections.selectedApp; - const client = state.connections.clients.find((client) => client.id === app); - if (!app || !client) { - throw new Error('Can only record plugin states if a device is selected'); - } - const selectedPlugin = state.connections.selectedPlugin; - const pluginKey = getPluginKey(client.id, null, selectedPlugin!); - const plugin = state.plugins.clientPlugins.get(selectedPlugin!); - if (!selectedPlugin || !plugin) { - throw new Error('Can only record plugin states if a plugin is selected'); - } - pluginRecordingState = { - recording: pluginKey, - startState: undefined, - events: [], - endState: undefined, - pluginName: selectedPlugin, - }; - - // Note that we don't use the plugin's own serializeState, as that might interact with the - // device state, and is used for creating Flipper Exports. - pluginRecordingState.startState = await serialize( - state.pluginStates[pluginKey] || - (isSandyPlugin(plugin) ? {} : plugin.defaultPersistedState), - ); - - console.log( - `Started recordig the states of plugin ${selectedPlugin}..... Use window.flipperStopPluginRecording() to finish this process`, - ); -} - -async function flipperStopPluginRecording(state: State) { - if (!pluginRecordingState.recording) { - throw new Error('No plugin recording is running. '); - } - if (!pluginRecordingState.events.length) { - console.warn('No events were captured, cancelling recording'); - pluginRecordingState = initialRecordingState(); - return; - } - - pluginRecordingState.endState = await serialize( - state.pluginStates[pluginRecordingState.recording], - ); - - const pluginName = pluginRecordingState.pluginName; - const snapShotFileContents = JSON.stringify(pluginRecordingState); - const snapShotFileName = `${pluginName}.pluginSnapshot.json`; - const testFileName = `${pluginName}EventsRunner.tsx`; - const outDir = getOutputDir(pluginName); - - const testFileContents = generateTestSuite(pluginName, snapShotFileName); - - await fs.promises.writeFile( - path.join(outDir, snapShotFileName), - snapShotFileContents, - 'utf8', - ); - await fs.promises.writeFile( - path.join(outDir, testFileName), - testFileContents, - 'utf8', - ); - - console.log( - `Finished recording ${pluginRecordingState.events.length} for plugin ${ - pluginRecordingState.recording - }. Generated files ${path.join(outDir, testFileName)} and ${path.join( - outDir, - snapShotFileName, - )}. Move them to the '__tests__ folder of your plugin to incorporate them`, - ); - pluginRecordingState = initialRecordingState(); -} - -export function registerRecordingHooks(store: Store) { - Object.assign(window, { - flipperStartPluginRecording() { - flipperStartPluginRecording(store.getState()); - }, - flipperStopPluginRecording() { - flipperStopPluginRecording(store.getState()); - }, - }); -} - -function getOutputDir(pluginName: string) { - const outDir = path.join(process.cwd(), '..'); - const fbPluginDir = path.join( - outDir, - 'plugins', - 'fb', - pluginName.toLowerCase(), - '__tests__', - ); - const defaultPluginDir = path.join( - outDir, - 'plugins', - pluginName.toLowerCase(), - '__tests__', - ); - - if (fs.existsSync(fbPluginDir)) { - return fbPluginDir; - } else if (fs.existsSync(defaultPluginDir)) { - return defaultPluginDir; - } - return outDir; -} - -function generateTestSuite(pluginName: string, snapShotFileName: string) { - return `\ -/** - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -// This file was initially generated by using \`flipperStartPluginRecording()\` in Flipper console - -import fs from 'fs'; -import path from 'path'; -import {deserialize} from '../ui'; -import Plugin from '../'; - -test('Verify events produce a consistent end state for plugin ${pluginName}', async () => { - const snapshotData: { - startState: string; - endState: string; - events: [string, any][]; - } = JSON.parse( - await fs.promises.readFile( - path.join(__dirname, '${snapShotFileName}'), - 'utf8', - ), - ); - - const startState: typeof Plugin.defaultPersistedState = deserialize( - snapshotData.startState, - ); - const endState: typeof Plugin.defaultPersistedState = deserialize( - snapshotData.endState, - ); - const startTime = Date.now(); - - const generatedEndState = snapshotData.events.reduce( - (store, [method, params]) => - Plugin.persistedStateReducer(store, method, params), - startState, - ); - - const totalTime = Date.now() - startTime; - - expect(generatedEndState).toEqual(endState); - console.log( - \`Reducer took $\{totalTime\}ms. to process $\{snapshotData.events.length\} events\`, - ); -}); - -`; -}