|  | // 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 {mergeCallsites} from './flamegraph_util'; | 
|  | import {CallsiteInfo} from './state'; | 
|  |  | 
|  | 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); | 
|  | }); |