forked from firefox-devtools/profiler
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBottomBox.test.js
183 lines (154 loc) · 6.06 KB
/
BottomBox.test.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// @flow
import React from 'react';
import { Provider } from 'react-redux';
import { stripIndent } from 'common-tags';
import { ProfileViewer } from 'firefox-profiler/components/app/ProfileViewer';
import { updateUrlState } from 'firefox-profiler/actions/app';
import { viewProfile } from 'firefox-profiler/actions/receive-profile';
import { stateFromLocation } from 'firefox-profiler/app-logic/url-handling';
import { ensureExists } from 'firefox-profiler/utils/flow';
import {
render,
screen,
within,
} from 'firefox-profiler/test/fixtures/testing-library';
import { blankStore } from 'firefox-profiler/test/fixtures/stores';
import { getProfileFromTextSamples } from 'firefox-profiler/test/fixtures/profiles/processed-profile';
import { fireFullClick } from 'firefox-profiler/test/fixtures/utils';
import { autoMockDomRect } from 'firefox-profiler/test/fixtures/mocks/domrect.js';
// We're not interested in the timeline in this test
jest.mock('../../components/timeline', () => ({
Timeline: 'custom-timeline',
}));
describe('BottomBox', () => {
autoMockDomRect();
afterEach(() => {
delete Range.prototype.getClientRects;
});
function setup() {
if (Range.prototype.getClientRects) {
throw new Error(
'jsdom now implements Range.prototype.getClientRects, please update this test.'
);
}
// @codemirror/view uses getClientRects when scrolling.
// $FlowExpectError because Flow doesn't accept assigning a function to getClientRects.
Range.prototype.getClientRects = () => {
return [new DOMRect(0, 0, 1024, 768)];
};
const revision = '997f00815e6bc28806b75448c8829f0259d2cb28';
const filepath = 'widget/cocoa/nsAppShell.mm';
window.fetch
.post('http://127.0.0.1:8000/source/v1', 500)
.get(
`https://hg.mozilla.org/mozilla-central/raw-file/${revision}/${filepath}`,
stripIndent`
line 1
line 2
line 3
line 4
line 5
line 6
line 7
`
)
.post(
'http://127.0.0.1:8000/asm/v1',
JSON.stringify({
startAddress: '0x20',
size: '0x1a',
arch: 'x86_64',
syntax: ['Intel'],
instructions: [
[0, 'push rsi'],
[1, 'push rdi'],
[2, 'push rbx'],
[3, 'sub rsp, 0x20'],
[7, 'mov rsi, rcx'],
[10, 'mov rdi, qword [rcx + 0x58]'],
[14, 'mov ebx, edi'],
[16, 'and ebx, 0x1400'],
[22, 'call 0x16c5d35'],
],
})
);
const { profile } = getProfileFromTextSamples(`
A[file:hg:hg.mozilla.org/mozilla-central:${filepath}:${revision}][line:4][address:30][sym:Asym:20:1a][lib:libA.so]
B[file:git:github.com/rust-lang/rust:library/std/src/sys/unix/thread.rs:53cb7b09b00cbea8754ffb78e7e3cb521cb8af4b]
C[lib:libC.so][file:s3:gecko-generated-sources:a5d3747707d6877b0e5cb0a364e3cb9fea8aa4feb6ead138952c2ba46d41045297286385f0e0470146f49403e46bd266e654dfca986de48c230f3a71c2aafed4/ipc/ipdl/PBackgroundChild.cpp:]
D[lib:libD.so]
`);
const store = blankStore();
store.dispatch(
updateUrlState(
stateFromLocation({
pathname: '/from-browser',
search: '?symbolServer=http://127.0.0.1:8000',
hash: '',
})
)
);
store.dispatch(viewProfile(profile));
render(
<Provider store={store}>
<ProfileViewer />
</Provider>
);
return {
sourceView: () => document.querySelector('.sourceView'),
assemblyView: () => document.querySelector('.assemblyView'),
};
}
it('does not show the source view at loadtime', () => {
const { sourceView, assemblyView } = setup();
expect(sourceView()).not.toBeInTheDocument();
expect(assemblyView()).not.toBeInTheDocument();
});
it('should show the source view when a line in the tree view is double-clicked', async () => {
const { sourceView, assemblyView } = setup();
const frameElement = screen.getByRole('treeitem', { name: /^A/ });
fireFullClick(frameElement);
fireFullClick(frameElement, { detail: 2 });
expect(sourceView()).toBeInTheDocument();
expect(assemblyView()).not.toBeInTheDocument();
const sourceViewElement = ensureExists(sourceView());
const sourceViewContent =
await within(sourceViewElement).findByRole('textbox');
// Because numbers and strings are split in several element, we're matching
// on the string "line" only.
await within(sourceViewContent).findAllByText('line');
expect(sourceViewContent).toMatchSnapshot();
});
it('should show the assembly view when pressing the toggle button', async () => {
const { sourceView, assemblyView } = setup();
const frameElement = screen.getByRole('treeitem', { name: /^A/ });
fireFullClick(frameElement);
fireFullClick(frameElement, { detail: 2 });
expect(sourceView()).toBeInTheDocument();
expect(assemblyView()).not.toBeInTheDocument();
const asmViewShowButton = ensureExists(
document.querySelector('.bottom-assembly-button')
);
fireFullClick(asmViewShowButton);
expect(sourceView()).toBeInTheDocument();
expect(assemblyView()).toBeInTheDocument();
const assemblyViewElement = ensureExists(assemblyView());
const assemblyViewContent =
await within(assemblyViewElement).findByRole('textbox');
// Find one of the instructions. Once we have assembly syntax highlighting,
// we'll probably have to match on a smaller string.
await within(assemblyViewContent).findAllByText(
'mov rdi, qword [rcx + 0x58]'
);
expect(assemblyViewContent).toMatchSnapshot();
// Click the toggle button again and make sure the assembly view hides.
const asmViewHideButton = ensureExists(
document.querySelector('.bottom-assembly-button')
);
fireFullClick(asmViewHideButton);
expect(assemblyView()).not.toBeInTheDocument();
});
});