Parse Date from the crash and fix the date mismatch in the UI

Summary:
This diff parses the `Date` from the crash log, so that the `Date` shown on the UI matches with the actual crash log
Bug:

{F154301489}

Added test too

Reviewed By: danielbuechele

Differential Revision: D14563053

fbshipit-source-id: b9dc7de11d7f17d6c7aa2afe5106b8f85c0a535c
This commit is contained in:
Pritesh Nandgaonkar
2019-03-25 04:50:07 -07:00
committed by Facebook Github Bot
parent 0adc2ef52e
commit dd3f0fdfeb
2 changed files with 46 additions and 5 deletions

View File

@@ -64,14 +64,26 @@ afterAll(() => {
setCrashReporterPluginID(''); setCrashReporterPluginID('');
}); });
test('test the parsing of the reason for crash when log matches the predefined regex', () => { test('test the parsing of the date and crash info for the log which matches the predefined regex', () => {
const log =
'Blaa Blaaa \n Blaa Blaaa \n Exception Type: SIGSEGV \n Blaa Blaa \n Blaa Blaa Date/Time: 2019-03-21 12:07:00.861 +0000 \n Blaa balaaa';
const crash = parseCrashLog(log, 'iOS');
expect(crash.callstack).toEqual(log);
expect(crash.reason).toEqual('SIGSEGV');
expect(crash.name).toEqual('SIGSEGV');
expect(crash.date).toEqual(new Date('2019-03-21 12:07:00.861'));
});
test('test the parsing of the reason for crash when log matches the crash regex, but there is no mention of date', () => {
const log = const log =
'Blaa Blaaa \n Blaa Blaaa \n Exception Type: SIGSEGV \n Blaa Blaa \n Blaa Blaa'; 'Blaa Blaaa \n Blaa Blaaa \n Exception Type: SIGSEGV \n Blaa Blaa \n Blaa Blaa';
const crash = parseCrashLog(log, 'iOS'); const crash = parseCrashLog(log, 'iOS');
expect(crash.callstack).toEqual(log); expect(crash.callstack).toEqual(log);
expect(crash.reason).toEqual('SIGSEGV'); expect(crash.reason).toEqual('SIGSEGV');
expect(crash.name).toEqual('SIGSEGV'); expect(crash.name).toEqual('SIGSEGV');
expect(crash.date).toBeUndefined();
}); });
test('test the parsing of the crash log when log does not match the predefined regex but is alphanumeric', () => { test('test the parsing of the crash log when log does not match the predefined regex but is alphanumeric', () => {
const log = 'Blaa Blaaa \n Blaa Blaaa \n Blaa Blaaa'; const log = 'Blaa Blaaa \n Blaa Blaaa \n Blaa Blaaa';
const crash = parseCrashLog(log, 'iOS'); const crash = parseCrashLog(log, 'iOS');
@@ -87,6 +99,7 @@ test('test the parsing of the reason for crash when log does not match the prede
expect(crash.callstack).toEqual(log); expect(crash.callstack).toEqual(log);
expect(crash.reason).toEqual('Cannot figure out the cause'); expect(crash.reason).toEqual('Cannot figure out the cause');
expect(crash.name).toEqual('Cannot figure out the cause'); expect(crash.name).toEqual('Cannot figure out the cause');
expect(crash.date).toBeUndefined();
}); });
test('test the parsing of the reason for crash when log is empty', () => { test('test the parsing of the reason for crash when log is empty', () => {
const log = ''; const log = '';
@@ -94,23 +107,27 @@ test('test the parsing of the reason for crash when log is empty', () => {
expect(crash.callstack).toEqual(log); expect(crash.callstack).toEqual(log);
expect(crash.reason).toEqual('Cannot figure out the cause'); expect(crash.reason).toEqual('Cannot figure out the cause');
expect(crash.name).toEqual('Cannot figure out the cause'); expect(crash.name).toEqual('Cannot figure out the cause');
expect(crash.date).toBeUndefined();
}); });
test('test the parsing of the Android crash log for the proper android crash format', () => { test('test the parsing of the Android crash log for the proper android crash format', () => {
const log = const log =
'FATAL EXCEPTION: main\nProcess: com.facebook.flipper.sample, PID: 27026\njava.lang.IndexOutOfBoundsException: Index: 190, Size: 0\n\tat java.util.ArrayList.get(ArrayList.java:437)\n\tat com.facebook.flipper.sample.RootComponentSpec.hitGetRequest(RootComponentSpec.java:72)\n\tat com.facebook.flipper.sample.RootComponent.hitGetRequest(RootComponent.java:46)\n'; 'FATAL EXCEPTION: main\nProcess: com.facebook.flipper.sample, PID: 27026\njava.lang.IndexOutOfBoundsException: Index: 190, Size: 0\n\tat java.util.ArrayList.get(ArrayList.java:437)\n\tat com.facebook.flipper.sample.RootComponentSpec.hitGetRequest(RootComponentSpec.java:72)\n\tat com.facebook.flipper.sample.RootComponent.hitGetRequest(RootComponent.java:46)\n';
const crash = parseCrashLog(log, 'Android'); const date = new Date();
const crash = parseCrashLog(log, 'Android', date);
expect(crash.callstack).toEqual(log); expect(crash.callstack).toEqual(log);
expect(crash.reason).toEqual( expect(crash.reason).toEqual(
'java.lang.IndexOutOfBoundsException: Index: 190, Size: 0', 'java.lang.IndexOutOfBoundsException: Index: 190, Size: 0',
); );
expect(crash.name).toEqual('FATAL EXCEPTION: main'); expect(crash.name).toEqual('FATAL EXCEPTION: main');
expect(crash.date).toEqual(date);
}); });
test('test the parsing of the Android crash log for the unknown crash format', () => { test('test the parsing of the Android crash log for the unknown crash format and no date', () => {
const log = 'Blaa Blaa Blaa'; const log = 'Blaa Blaa Blaa';
const crash = parseCrashLog(log, 'Android'); const crash = parseCrashLog(log, 'Android');
expect(crash.callstack).toEqual(log); expect(crash.callstack).toEqual(log);
expect(crash.reason).toEqual('Cannot figure out the cause'); expect(crash.reason).toEqual('Cannot figure out the cause');
expect(crash.name).toEqual('Cannot figure out the cause'); expect(crash.name).toEqual('Cannot figure out the cause');
expect(crash.date).toBeUndefined();
}); });
test('test the parsing of the Android crash log for the partial format matching the crash format', () => { test('test the parsing of the Android crash log for the partial format matching the crash format', () => {
const log = 'First Line Break \n Blaa Blaa \n Blaa Blaa '; const log = 'First Line Break \n Blaa Blaa \n Blaa Blaa ';

View File

@@ -66,6 +66,7 @@ export type CrashLog = {|
callstack: string, callstack: string,
reason: string, reason: string,
name: string, name: string,
date: ?Date,
|}; |};
export type PersistedState = { export type PersistedState = {
@@ -164,12 +165,13 @@ export function getNewPersisitedStateFromCrashLog(
persistingPlugin: Class<FlipperDevicePlugin<> | FlipperPlugin<>>, persistingPlugin: Class<FlipperDevicePlugin<> | FlipperPlugin<>>,
content: string, content: string,
os: ?OS, os: ?OS,
logDate: ?Date,
): ?PersistedState { ): ?PersistedState {
const persistedStateReducer = persistingPlugin.persistedStateReducer; const persistedStateReducer = persistingPlugin.persistedStateReducer;
if (!os || !persistedStateReducer) { if (!os || !persistedStateReducer) {
return null; return null;
} }
const crash = parseCrashLog(content, os); const crash = parseCrashLog(content, os, logDate);
const newPluginState = persistedStateReducer( const newPluginState = persistedStateReducer(
persistedState, persistedState,
'crash-report', 'crash-report',
@@ -185,6 +187,7 @@ export function parseCrashLogAndUpdateState(
pluginKey: string, pluginKey: string,
newPluginState: ?PersistedState, newPluginState: ?PersistedState,
) => void, ) => void,
logDate: ?Date,
) { ) {
const os = store.getState().connections.selectedDevice?.os; const os = store.getState().connections.selectedDevice?.os;
if ( if (
@@ -219,6 +222,7 @@ export function parseCrashLogAndUpdateState(
persistingPlugin, persistingPlugin,
content, content,
os, os,
logDate,
); );
setPersistedState(pluginKey, newPluginState); setPersistedState(pluginKey, newPluginState);
} }
@@ -240,7 +244,11 @@ export function shouldShowCrashNotification(
return true; return true;
} }
export function parseCrashLog(content: string, os: OS): CrashLog { export function parseCrashLog(
content: string,
os: OS,
logDate: ?Date,
): CrashLog {
const stubString = 'Cannot figure out the cause'; const stubString = 'Cannot figure out the cause';
switch (os) { switch (os) {
case 'iOS': { case 'iOS': {
@@ -251,10 +259,24 @@ export function parseCrashLog(content: string, os: OS): CrashLog {
const tmp = exceptionRegex.exec(exceptionString); const tmp = exceptionRegex.exec(exceptionString);
const exception = const exception =
tmp && tmp[0].length ? tmp[0] : 'Cannot figure out the cause'; tmp && tmp[0].length ? tmp[0] : 'Cannot figure out the cause';
let date = logDate;
if (!date) {
const dateRegex = /Date\/Time: *[\w\s\.:-]*/;
const dateArr = dateRegex.exec(content);
const dateString = dateArr ? dateArr[0] : '';
const dateRegex2 = /[\w\s\.:-]*$/;
const tmp1 = dateRegex2.exec(dateString);
const extractedDateString: ?string =
tmp1 && tmp1[0].length ? tmp1[0] : null;
date = extractedDateString ? new Date(extractedDateString) : logDate;
}
const crash = { const crash = {
callstack: content, callstack: content,
name: exception, name: exception,
reason: exception, reason: exception,
date,
}; };
return crash; return crash;
} }
@@ -281,6 +303,7 @@ export function parseCrashLog(content: string, os: OS): CrashLog {
callstack: content, callstack: content,
name: name, name: name,
reason: reason, reason: reason,
date: logDate,
}; };
return crash; return crash;
} }
@@ -542,6 +565,7 @@ export default class CrashReporterPlugin extends FlipperDevicePlugin<
store, store,
androidLog, androidLog,
setPersistedState, setPersistedState,
entry.date,
); );
} }
androidLogUnderProcess = false; androidLogUnderProcess = false;