Update logic to parse crash for android
Summary: Updated the logic of parsing the crash log. Earlier the function written to parse crash log just expected the iOS crashes. Now it also gets android crash logs. I have also written the tests for the same and updated the tests to accommodate for the API change Reviewed By: passy Differential Revision: D13612576 fbshipit-source-id: cf7e9d2bca4a425ad7338fc5ec15e29cf88e2e77
This commit is contained in:
committed by
Facebook Github Bot
parent
cc0615c7d9
commit
972f8b91d6
@@ -56,14 +56,14 @@ afterAll(() => {
|
||||
test('test the parsing of the reason for crash when log matches the predefined regex', () => {
|
||||
const log =
|
||||
'Blaa Blaaa \n Blaa Blaaa \n Exception Type: SIGSEGV \n Blaa Blaa \n Blaa Blaa';
|
||||
const crash = parseCrashLog(log);
|
||||
const crash = parseCrashLog(log, 'iOS');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('SIGSEGV');
|
||||
expect(crash.name).toEqual('SIGSEGV');
|
||||
});
|
||||
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 crash = parseCrashLog(log);
|
||||
const crash = parseCrashLog(log, 'iOS');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('Cannot figure out the cause');
|
||||
expect(crash.name).toEqual('Cannot figure out the cause');
|
||||
@@ -72,14 +72,46 @@ test('test the parsing of the crash log when log does not match the predefined r
|
||||
test('test the parsing of the reason for crash when log does not match the predefined regex contains unicode character', () => {
|
||||
const log =
|
||||
'Blaa Blaaa \n Blaa Blaaa \n Exception Type: 🍕🐬 \n Blaa Blaa \n Blaa Blaa';
|
||||
const crash = parseCrashLog(log);
|
||||
const crash = parseCrashLog(log, 'iOS');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('Cannot figure out the cause');
|
||||
expect(crash.name).toEqual('Cannot figure out the cause');
|
||||
});
|
||||
test('test the parsing of the reason for crash when log is empty', () => {
|
||||
const log = '';
|
||||
const crash = parseCrashLog(log);
|
||||
const crash = parseCrashLog(log, 'iOS');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('Cannot figure out the cause');
|
||||
expect(crash.name).toEqual('Cannot figure out the cause');
|
||||
});
|
||||
test('test the parsing of the Android crash log for the proper android crash format', () => {
|
||||
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';
|
||||
const crash = parseCrashLog(log, 'Android');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual(
|
||||
'java.lang.IndexOutOfBoundsException: Index: 190, Size: 0',
|
||||
);
|
||||
expect(crash.name).toEqual('FATAL EXCEPTION: main');
|
||||
});
|
||||
test('test the parsing of the Android crash log for the unknown crash format', () => {
|
||||
const log = 'Blaa Blaa Blaa';
|
||||
const crash = parseCrashLog(log, 'Android');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('Cannot figure out the cause');
|
||||
expect(crash.name).toEqual('Cannot figure out the cause');
|
||||
});
|
||||
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 crash = parseCrashLog(log, 'Android');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('Cannot figure out the cause');
|
||||
expect(crash.name).toEqual('First Line Break ');
|
||||
});
|
||||
test('test the parsing of the Android crash log with os being iOS', () => {
|
||||
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';
|
||||
const crash = parseCrashLog(log, 'iOS');
|
||||
expect(crash.callstack).toEqual(log);
|
||||
expect(crash.reason).toEqual('Cannot figure out the cause');
|
||||
expect(crash.name).toEqual('Cannot figure out the cause');
|
||||
@@ -152,6 +184,7 @@ test('test getNewPersisitedStateFromCrashLog for non-empty defaultPersistedState
|
||||
perisistedState,
|
||||
CrashReporterPlugin,
|
||||
content,
|
||||
'iOS',
|
||||
);
|
||||
expect(newPersistedState).toEqual({
|
||||
crashes: [pluginStateCrash, getCrash(1, content, 'SIGSEGV', 'SIGSEGV')],
|
||||
@@ -174,6 +207,7 @@ test('test getNewPersisitedStateFromCrashLog for non-empty defaultPersistedState
|
||||
perisistedState,
|
||||
CrashReporterPlugin,
|
||||
content,
|
||||
'iOS',
|
||||
);
|
||||
expect(newPersistedState).toEqual({
|
||||
crashes: [crash, getCrash(1, content, 'SIGSEGV', 'SIGSEGV')],
|
||||
@@ -197,6 +231,7 @@ test('test getNewPersisitedStateFromCrashLog for non-empty defaultPersistedState
|
||||
perisistedState,
|
||||
CrashReporterPlugin,
|
||||
content,
|
||||
'iOS',
|
||||
);
|
||||
expect(newPersistedState).toEqual({
|
||||
crashes: [
|
||||
@@ -210,6 +245,26 @@ test('test getNewPersisitedStateFromCrashLog for non-empty defaultPersistedState
|
||||
],
|
||||
});
|
||||
});
|
||||
test('test getNewPersisitedStateFromCrashLog when os is undefined', () => {
|
||||
setNotificationID(0);
|
||||
const crash = getCrash(0, 'callstack', 'crash0', 'crash0');
|
||||
const pluginKey = getPluginKey(null, null, CrashReporterPlugin.id);
|
||||
setDefaultPersistedState({crashes: [crash]});
|
||||
const pluginStateCrash = getCrash(1, 'callstack', 'crash1', 'crash1');
|
||||
const pluginStates = {'unknown#CrashReporter': {crashes: [pluginStateCrash]}};
|
||||
const perisistedState = getPersistedState(
|
||||
pluginKey,
|
||||
CrashReporterPlugin,
|
||||
pluginStates,
|
||||
);
|
||||
const content = 'Blaa Blaaa \n Blaa Blaaa';
|
||||
const newPersistedState = getNewPersisitedStateFromCrashLog(
|
||||
perisistedState,
|
||||
CrashReporterPlugin,
|
||||
content,
|
||||
);
|
||||
expect(newPersistedState).toEqual(null);
|
||||
});
|
||||
test('test parsing of path when inputs are correct', () => {
|
||||
const content =
|
||||
'Blaa Blaaa \n Blaa Blaaa \n Path: path/to/simulator/TH1S-15DEV1CE-1D/AppName.app/AppName \n Blaa Blaa \n Blaa Blaa';
|
||||
|
||||
@@ -82,12 +82,14 @@ export function getNewPersisitedStateFromCrashLog(
|
||||
persistedState: ?PersistedState,
|
||||
persistingPlugin: Class<FlipperDevicePlugin<> | FlipperPlugin<>>,
|
||||
content: string,
|
||||
os: ?string,
|
||||
): ?PersistedState {
|
||||
const crash = parseCrashLog(content);
|
||||
if (!persistingPlugin.persistedStateReducer) {
|
||||
const persistedStateReducer = persistingPlugin.persistedStateReducer;
|
||||
if (!os || !persistedStateReducer) {
|
||||
return null;
|
||||
}
|
||||
const newPluginState = persistingPlugin.persistedStateReducer(
|
||||
const crash = parseCrashLog(content, os);
|
||||
const newPluginState = persistedStateReducer(
|
||||
persistedState,
|
||||
'crash-report',
|
||||
crash,
|
||||
@@ -103,11 +105,12 @@ export function parseCrashLogAndUpdateState(
|
||||
newPluginState: ?PersistedState,
|
||||
) => void,
|
||||
) {
|
||||
const os = store.getState().connections.selectedDevice?.os;
|
||||
if (
|
||||
!shouldShowCrashNotification(
|
||||
store.getState().connections.selectedDevice,
|
||||
content,
|
||||
store.getState().connections.selectedDevice?.os,
|
||||
os,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@@ -134,6 +137,7 @@ export function parseCrashLogAndUpdateState(
|
||||
persistedState,
|
||||
persistingPlugin,
|
||||
content,
|
||||
os,
|
||||
);
|
||||
setPersistedState(pluginKey, newPluginState);
|
||||
}
|
||||
@@ -155,20 +159,49 @@ export function shouldShowCrashNotification(
|
||||
return true;
|
||||
}
|
||||
|
||||
export function parseCrashLog(content: string): CrashLog {
|
||||
const regex = /Exception Type: *[\w]*/;
|
||||
const arr = regex.exec(content);
|
||||
const exceptionString = arr ? arr[0] : '';
|
||||
const exceptionRegex = /[\w]*$/;
|
||||
const tmp = exceptionRegex.exec(exceptionString);
|
||||
const exception =
|
||||
tmp && tmp[0].length ? tmp[0] : 'Cannot figure out the cause';
|
||||
const crash = {
|
||||
callstack: content,
|
||||
name: exception,
|
||||
reason: exception,
|
||||
};
|
||||
return crash;
|
||||
export function parseCrashLog(content: string, os: string): CrashLog {
|
||||
const stubString = 'Cannot figure out the cause';
|
||||
if (os.includes('iOS')) {
|
||||
const regex = /Exception Type: *[\w]*/;
|
||||
const arr = regex.exec(content);
|
||||
const exceptionString = arr ? arr[0] : '';
|
||||
const exceptionRegex = /[\w]*$/;
|
||||
const tmp = exceptionRegex.exec(exceptionString);
|
||||
const exception =
|
||||
tmp && tmp[0].length ? tmp[0] : 'Cannot figure out the cause';
|
||||
const crash = {
|
||||
callstack: content,
|
||||
name: exception,
|
||||
reason: exception,
|
||||
};
|
||||
return crash;
|
||||
} else if (os.includes('Android')) {
|
||||
const regForName = /.*\n/;
|
||||
const nameRegArr = regForName.exec(content);
|
||||
let name = nameRegArr ? nameRegArr[0] : stubString;
|
||||
const regForCallStack = /\tat[\w\s\n.$&+,:;=?@#|'<>.^*()%!-]*$/;
|
||||
const callStackArray = regForCallStack.exec(content);
|
||||
const callStack = callStackArray ? callStackArray[0] : '';
|
||||
let remainingString =
|
||||
callStack.length > 0 ? content.replace(callStack, '') : '';
|
||||
if (remainingString[remainingString.length - 1] === '\n') {
|
||||
remainingString = remainingString.slice(0, -1);
|
||||
}
|
||||
const reason =
|
||||
remainingString.length > 0
|
||||
? remainingString.split('\n').pop()
|
||||
: stubString;
|
||||
if (name[name.length - 1] === '\n') {
|
||||
name = name.slice(0, -1);
|
||||
}
|
||||
const crash = {
|
||||
callstack: content,
|
||||
name: name,
|
||||
reason: reason,
|
||||
};
|
||||
return crash;
|
||||
}
|
||||
throw new Error('Unsupported OS');
|
||||
}
|
||||
|
||||
export function parsePath(content: string): ?string {
|
||||
|
||||
Reference in New Issue
Block a user