| // Copyright (C) 2019 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| import {CallsiteInfo, mergeCallsites} from './legacy_flamegraph_util'; |
| |
| test('zeroCallsitesMerged', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 4, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 2, |
| name: 'B4', |
| depth: 1, |
| totalSize: 4, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 5); |
| |
| // Small callsites are not next ot each other, nothing should be changed. |
| expect(mergedCallsites).toEqual(callsites); |
| }); |
| |
| test('zeroCallsitesMerged2', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 6, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: 'A4', |
| depth: 1, |
| totalSize: 4, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 5, |
| parentId: 2, |
| name: 'B5', |
| depth: 1, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 5); |
| |
| // Small callsites are not next ot each other, nothing should be changed. |
| expect(mergedCallsites).toEqual(callsites); |
| }); |
| |
| test('twoCallsitesMerged', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: 'A2', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 6); |
| |
| expect(mergedCallsites).toEqual([ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: '[merged]', |
| depth: 1, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| ]); |
| }); |
| |
| test('manyCallsitesMerged', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: 'A2', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 3, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: 'A4', |
| depth: 1, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 5, |
| parentId: 1, |
| name: 'A5', |
| depth: 1, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 6, |
| parentId: 3, |
| name: 'A36', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 7, |
| parentId: 4, |
| name: 'A47', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 8, |
| parentId: 5, |
| name: 'A58', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const expectedMergedCallsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: 'A2', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: '[merged]', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| { |
| id: 6, |
| parentId: 3, |
| name: '[merged]', |
| depth: 2, |
| totalSize: 3, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 4); |
| |
| // In this case, callsites A3, A4 and A5 should be merged since they are |
| // smaller then 4 and are on same depth with same parent. Callsites A36, A47 |
| // and A58 should also be merged since their parents are merged. |
| expect(mergedCallsites).toEqual(expectedMergedCallsites); |
| }); |
| |
| test('manyCallsitesMergedWithoutChildren', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 3, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: 'A4', |
| depth: 1, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 5, |
| parentId: 1, |
| name: 'A5', |
| depth: 1, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 6, |
| parentId: 2, |
| name: 'B6', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 7, |
| parentId: 4, |
| name: 'A47', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 8, |
| parentId: 6, |
| name: 'B68', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const expectedMergedCallsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: '[merged]', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| { |
| id: 6, |
| parentId: 2, |
| name: 'B6', |
| depth: 1, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 7, |
| parentId: 3, |
| name: 'A47', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 8, |
| parentId: 6, |
| name: 'B68', |
| depth: 2, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 4); |
| |
| // In this case, callsites A3, A4 and A5 should be merged since they are |
| // smaller then 4 and are on same depth with same parent. Callsite A47 |
| // should not be merged with B68 althought they are small because they don't |
| // have sam parent. A47 should now have parent A3 because A4 is merged. |
| expect(mergedCallsites).toEqual(expectedMergedCallsites); |
| }); |
| |
| test('smallCallsitesNotNextToEachOtherInArray', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 20, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: 'A2', |
| depth: 1, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 1, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: 'A4', |
| depth: 1, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 5, |
| parentId: 1, |
| name: 'A5', |
| depth: 1, |
| totalSize: 3, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const expectedMergedCallsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 20, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: 'A2', |
| depth: 1, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: '[merged]', |
| depth: 1, |
| totalSize: 4, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: 'A4', |
| depth: 1, |
| totalSize: 8, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 4); |
| |
| // In this case, callsites A3, A4 and A5 should be merged since they are |
| // smaller then 4 and are on same depth with same parent. Callsite A47 |
| // should not be merged with B68 althought they are small because they don't |
| // have sam parent. A47 should now have parent A3 because A4 is merged. |
| expect(mergedCallsites).toEqual(expectedMergedCallsites); |
| }); |
| |
| test('smallCallsitesNotMerged', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: 1, |
| name: 'A2', |
| depth: 1, |
| totalSize: 2, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 2, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 1); |
| |
| expect(mergedCallsites).toEqual(callsites); |
| }); |
| |
| test('mergingRootCallsites', () => { |
| const callsites: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 2, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const mergedCallsites = mergeCallsites(callsites, 20); |
| |
| expect(mergedCallsites).toEqual([ |
| { |
| id: 1, |
| parentId: -1, |
| name: '[merged]', |
| depth: 0, |
| totalSize: 12, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| ]); |
| }); |
| |
| test('largerFlamegraph', () => { |
| const data: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 60, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 40, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 25, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: 'A4', |
| depth: 1, |
| totalSize: 15, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 5, |
| parentId: 1, |
| name: 'A5', |
| depth: 1, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 6, |
| parentId: 1, |
| name: 'A6', |
| depth: 1, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 7, |
| parentId: 2, |
| name: 'B7', |
| depth: 1, |
| totalSize: 30, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 8, |
| parentId: 2, |
| name: 'B8', |
| depth: 1, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 9, |
| parentId: 3, |
| name: 'A39', |
| depth: 2, |
| totalSize: 20, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 10, |
| parentId: 4, |
| name: 'A410', |
| depth: 2, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 11, |
| parentId: 4, |
| name: 'A411', |
| depth: 2, |
| totalSize: 3, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 12, |
| parentId: 4, |
| name: 'A412', |
| depth: 2, |
| totalSize: 2, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 13, |
| parentId: 5, |
| name: 'A513', |
| depth: 2, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 14, |
| parentId: 5, |
| name: 'A514', |
| depth: 2, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 15, |
| parentId: 7, |
| name: 'A715', |
| depth: 2, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 16, |
| parentId: 7, |
| name: 'A716', |
| depth: 2, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 17, |
| parentId: 7, |
| name: 'A717', |
| depth: 2, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 18, |
| parentId: 7, |
| name: 'A718', |
| depth: 2, |
| totalSize: 5, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 19, |
| parentId: 9, |
| name: 'A919', |
| depth: 3, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 20, |
| parentId: 17, |
| name: 'A1720', |
| depth: 3, |
| totalSize: 2, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| const expectedData: CallsiteInfo[] = [ |
| { |
| id: 1, |
| parentId: -1, |
| name: 'A', |
| depth: 0, |
| totalSize: 60, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 2, |
| parentId: -1, |
| name: 'B', |
| depth: 0, |
| totalSize: 40, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 3, |
| parentId: 1, |
| name: 'A3', |
| depth: 1, |
| totalSize: 25, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 4, |
| parentId: 1, |
| name: '[merged]', |
| depth: 1, |
| totalSize: 35, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| { |
| id: 7, |
| parentId: 2, |
| name: 'B7', |
| depth: 1, |
| totalSize: 30, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 8, |
| parentId: 2, |
| name: 'B8', |
| depth: 1, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 9, |
| parentId: 3, |
| name: 'A39', |
| depth: 2, |
| totalSize: 20, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 10, |
| parentId: 4, |
| name: '[merged]', |
| depth: 2, |
| totalSize: 25, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| { |
| id: 15, |
| parentId: 7, |
| name: '[merged]', |
| depth: 2, |
| totalSize: 25, |
| selfSize: 0, |
| mapping: 'x', |
| merged: true, |
| highlighted: false, |
| }, |
| { |
| id: 19, |
| parentId: 9, |
| name: 'A919', |
| depth: 3, |
| totalSize: 10, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| { |
| id: 20, |
| parentId: 15, |
| name: 'A1720', |
| depth: 3, |
| totalSize: 2, |
| selfSize: 0, |
| mapping: 'x', |
| merged: false, |
| highlighted: false, |
| }, |
| ]; |
| |
| // In this case, on depth 1, callsites A4, A5 and A6 should be merged and |
| // initiate merging of their children A410, A411, A412, A513, A514. On depth2, |
| // callsites A715, A716, A717 and A718 should be merged. |
| const actualData = mergeCallsites(data, 16); |
| |
| expect(actualData).toEqual(expectedData); |
| }); |