зеркало из https://github.com/mozilla/treeherder.git
Bug 1861899 - Ignore non-perf-test profiles in perf test job performance tab.
This commit is contained in:
Родитель
0060933159
Коммит
5a4df58ab0
|
@ -0,0 +1,186 @@
|
|||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import { Provider, ReactReduxContext } from 'react-redux';
|
||||
import { ConnectedRouter } from 'connected-react-router';
|
||||
|
||||
import {
|
||||
configureStore,
|
||||
history,
|
||||
} from '../../../ui/job-view/redux/configureStore';
|
||||
import PerformanceTab from '../../../ui/job-view/details/tabs/PerformanceTab.jsx';
|
||||
|
||||
describe('PerformanceTab', () => {
|
||||
const testPerformanceTab = ({
|
||||
selectedJobFull,
|
||||
jobDetails,
|
||||
perfJobDetail,
|
||||
}) => {
|
||||
const repoName = 'try';
|
||||
const currentRepo = { name: repoName };
|
||||
|
||||
const store = configureStore();
|
||||
|
||||
return (
|
||||
<Provider store={store} context={ReactReduxContext}>
|
||||
<ConnectedRouter history={history} context={ReactReduxContext}>
|
||||
<PerformanceTab
|
||||
selectedJobFull={selectedJobFull}
|
||||
currentRepo={currentRepo}
|
||||
repoName={repoName}
|
||||
jobDetails={jobDetails}
|
||||
perfJobDetail={perfJobDetail}
|
||||
revision="REV1"
|
||||
/>
|
||||
</ConnectedRouter>
|
||||
</Provider>
|
||||
);
|
||||
};
|
||||
|
||||
test('perf test job with no profile should show generate button', async () => {
|
||||
const { getByTestId, queryByTestId } = render(
|
||||
testPerformanceTab({
|
||||
selectedJobFull: {
|
||||
job_type_name:
|
||||
'test-macosx1015-64-shippable-qr/opt-browsertime-something',
|
||||
job_type_symbol: 'some',
|
||||
job_group_name: 'Browsertime performance tests on Firefox',
|
||||
hasSideBySide: false,
|
||||
},
|
||||
jobDetails: [],
|
||||
perfJobDetail: [],
|
||||
}),
|
||||
);
|
||||
|
||||
const generateProfile = await getByTestId('generate-profile');
|
||||
expect(generateProfile.textContent).toBe('Generate performance profile');
|
||||
|
||||
const openProfiler = queryByTestId('open-profiler');
|
||||
expect(openProfiler).toBeNull();
|
||||
});
|
||||
|
||||
test('perf test job with resource profile should show generate button', async () => {
|
||||
const { getByTestId, queryByTestId } = render(
|
||||
testPerformanceTab({
|
||||
selectedJobFull: {
|
||||
job_type_name:
|
||||
'test-macosx1015-64-shippable-qr/opt-browsertime-something',
|
||||
job_type_symbol: 'some',
|
||||
job_group_name: 'Browsertime performance tests on Firefox',
|
||||
hasSideBySide: false,
|
||||
},
|
||||
jobDetails: [
|
||||
{
|
||||
url: 'dummy',
|
||||
value: 'profile_resource-usage.json',
|
||||
},
|
||||
{
|
||||
url: 'dummy',
|
||||
value: 'profile_build_resources.json',
|
||||
},
|
||||
],
|
||||
perfJobDetail: [],
|
||||
}),
|
||||
);
|
||||
|
||||
const generateProfile = getByTestId('generate-profile');
|
||||
expect(generateProfile.textContent).toBe('Generate performance profile');
|
||||
|
||||
const openProfiler = queryByTestId('open-profiler');
|
||||
expect(openProfiler).toBeNull();
|
||||
});
|
||||
|
||||
test('perf test job with perf profile should show retrigger button and open button', async () => {
|
||||
const { getByTestId } = render(
|
||||
testPerformanceTab({
|
||||
selectedJobFull: {
|
||||
job_type_name:
|
||||
'test-macosx1015-64-shippable-qr/opt-browsertime-something',
|
||||
job_type_symbol: 'some',
|
||||
job_group_name: 'Browsertime performance tests on Firefox',
|
||||
hasSideBySide: false,
|
||||
},
|
||||
jobDetails: [
|
||||
{
|
||||
url: 'profile_something.zip',
|
||||
value: 'profile_something.zip',
|
||||
},
|
||||
],
|
||||
perfJobDetail: [],
|
||||
}),
|
||||
);
|
||||
|
||||
const generateProfile = getByTestId('generate-profile');
|
||||
expect(generateProfile.textContent).toBe('Re-trigger performance profile');
|
||||
|
||||
const openProfiler = getByTestId('open-profiler');
|
||||
expect(openProfiler.href).toBe(
|
||||
'https://profiler.firefox.com/from-url/profile_something.zip',
|
||||
);
|
||||
});
|
||||
|
||||
test('perf test job with both perf and resource profiles should use perf profile', async () => {
|
||||
const { getByTestId } = render(
|
||||
testPerformanceTab({
|
||||
selectedJobFull: {
|
||||
job_type_name:
|
||||
'test-macosx1015-64-shippable-qr/opt-browsertime-something',
|
||||
job_type_symbol: 'some',
|
||||
job_group_name: 'Browsertime performance tests on Firefox',
|
||||
hasSideBySide: false,
|
||||
},
|
||||
jobDetails: [
|
||||
{
|
||||
url: 'dummy',
|
||||
value: 'profile_resource-usage.json',
|
||||
},
|
||||
{
|
||||
url: 'profile_something.json',
|
||||
value: 'profile_something.json',
|
||||
},
|
||||
],
|
||||
perfJobDetail: [],
|
||||
}),
|
||||
);
|
||||
|
||||
const generateProfile = getByTestId('generate-profile');
|
||||
expect(generateProfile.textContent).toBe('Re-trigger performance profile');
|
||||
|
||||
const openProfiler = getByTestId('open-profiler');
|
||||
expect(openProfiler.href).toBe(
|
||||
'https://profiler.firefox.com/from-url/profile_something.json',
|
||||
);
|
||||
});
|
||||
|
||||
test('perf test should use most relevant profile', async () => {
|
||||
const { getByTestId } = render(
|
||||
testPerformanceTab({
|
||||
selectedJobFull: {
|
||||
job_type_name:
|
||||
'test-macosx1015-64-shippable-qr/opt-browsertime-something',
|
||||
job_type_symbol: 'some',
|
||||
job_group_name: 'Browsertime performance tests on Firefox',
|
||||
hasSideBySide: false,
|
||||
},
|
||||
jobDetails: [
|
||||
{
|
||||
url: 'profile_something.json',
|
||||
value: 'profile_something.json',
|
||||
},
|
||||
{
|
||||
url: 'profile_something.zip',
|
||||
value: 'profile_something.zip',
|
||||
},
|
||||
],
|
||||
perfJobDetail: [],
|
||||
}),
|
||||
);
|
||||
|
||||
const generateProfile = getByTestId('generate-profile');
|
||||
expect(generateProfile.textContent).toBe('Re-trigger performance profile');
|
||||
|
||||
const openProfiler = getByTestId('open-profiler');
|
||||
expect(openProfiler.href).toBe(
|
||||
'https://profiler.firefox.com/from-url/profile_something.zip',
|
||||
);
|
||||
});
|
||||
});
|
|
@ -24,6 +24,17 @@ import { geckoProfileTaskName, sxsTaskName } from '../../../helpers/constants';
|
|||
|
||||
import SideBySide from './SideBySide';
|
||||
import PerfData from './PerfData';
|
||||
|
||||
const PROFILE_ZIP_RELEVANCE = 4;
|
||||
const PROFILE_RESOURCE_RELEVANCE = 3;
|
||||
const PROFILE_BUILD_RELEVANCE = 2;
|
||||
const PROFILE_JSON_RELEVANCE = 1;
|
||||
const NO_PROFILE_RELEVANCE = 0;
|
||||
const NON_PERFTEST_RELEVANCES = [
|
||||
PROFILE_RESOURCE_RELEVANCE,
|
||||
PROFILE_BUILD_RELEVANCE,
|
||||
];
|
||||
|
||||
/**
|
||||
* The performance tab shows performance-oriented information about a test run.
|
||||
* It helps users interact with the Firefox Profiler, and summarizes test
|
||||
|
@ -74,16 +85,64 @@ class PerformanceTab extends React.PureComponent {
|
|||
);
|
||||
};
|
||||
|
||||
maybeGetFirefoxProfilerLink() {
|
||||
// Look for a profiler artifact.
|
||||
const jobDetail = this.props.jobDetails.find(
|
||||
({ url, value }) =>
|
||||
url &&
|
||||
value.startsWith('profile_') &&
|
||||
(value.endsWith('.zip') || value.endsWith('.json')),
|
||||
);
|
||||
getProfileRelevance = (jobDetail) => {
|
||||
const { url, value } = jobDetail;
|
||||
if (!url) {
|
||||
return NO_PROFILE_RELEVANCE;
|
||||
}
|
||||
|
||||
if (!value.startsWith('profile_')) {
|
||||
return NO_PROFILE_RELEVANCE;
|
||||
}
|
||||
|
||||
if (value.endsWith('.zip')) {
|
||||
return PROFILE_ZIP_RELEVANCE;
|
||||
}
|
||||
|
||||
if (!value.endsWith('.json')) {
|
||||
return NO_PROFILE_RELEVANCE;
|
||||
}
|
||||
|
||||
if (value === 'profile_resource-usage.json') {
|
||||
return PROFILE_RESOURCE_RELEVANCE;
|
||||
}
|
||||
|
||||
if (value === 'profile_build_resources.json') {
|
||||
return PROFILE_BUILD_RELEVANCE;
|
||||
}
|
||||
|
||||
return PROFILE_JSON_RELEVANCE;
|
||||
};
|
||||
|
||||
// Returns profile-related job details, ordered by the relevance.
|
||||
getProfiles = (perfTestOnly) => {
|
||||
const profiles = [];
|
||||
for (const jobDetail of this.props.jobDetails) {
|
||||
const relevance = this.getProfileRelevance(jobDetail);
|
||||
if (relevance === NO_PROFILE_RELEVANCE) {
|
||||
continue;
|
||||
}
|
||||
if (perfTestOnly) {
|
||||
if (NON_PERFTEST_RELEVANCES.includes(relevance)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
profiles.push({ jobDetail, relevance });
|
||||
}
|
||||
return profiles.sort((a, b) => b.relevance - a.relevance);
|
||||
};
|
||||
|
||||
maybeGetFirefoxProfilerLink = (perfTestOnly) => {
|
||||
const profiles = this.getProfiles(perfTestOnly);
|
||||
|
||||
if (profiles.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Use the most relevant profile.
|
||||
const { jobDetail } = profiles[0];
|
||||
|
||||
if (jobDetail) {
|
||||
return (
|
||||
<a
|
||||
title={jobDetail.value}
|
||||
|
@ -91,15 +150,13 @@ class PerformanceTab extends React.PureComponent {
|
|||
className="btn btn-darker-secondary btn-sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
data-testid="open-profiler"
|
||||
>
|
||||
<FontAwesomeIcon icon={faExternalLinkAlt} className="mr-2" />
|
||||
Open in Firefox Profiler
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
|
@ -110,7 +167,12 @@ class PerformanceTab extends React.PureComponent {
|
|||
perfJobDetail,
|
||||
} = this.props;
|
||||
const { triggeredGeckoProfiles, showSideBySide } = this.state;
|
||||
const profilerLink = this.maybeGetFirefoxProfilerLink();
|
||||
|
||||
// Just to be safe, use the same isPerfTest check the other
|
||||
// "Create Gecko Profile" button uses in the action menu.
|
||||
const perfTest = isPerfTest(selectedJobFull);
|
||||
|
||||
const profilerLink = this.maybeGetFirefoxProfilerLink(perfTest);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -124,10 +186,7 @@ class PerformanceTab extends React.PureComponent {
|
|||
// the primary action of the user here.
|
||||
profilerLink
|
||||
}
|
||||
{
|
||||
// Just to be safe, use the same isPerfTest check the other
|
||||
// "Create Gecko Profile" button uses in the action menu.
|
||||
isPerfTest(selectedJobFull) ? (
|
||||
{perfTest ? (
|
||||
<Button
|
||||
className={`btn ${
|
||||
// Only make this primary if there is no profiler link.
|
||||
|
@ -140,14 +199,14 @@ class PerformanceTab extends React.PureComponent {
|
|||
'Trigger another run of this test with the profiler enabled. The ' +
|
||||
'profile can then be viewed in the Firefox Profiler.'
|
||||
}
|
||||
data-testid="generate-profile"
|
||||
>
|
||||
<FontAwesomeIcon icon={faRedo} className="mr-2" />
|
||||
{profilerLink
|
||||
? 'Re-trigger performance profile'
|
||||
: 'Generate performance profile'}
|
||||
</Button>
|
||||
) : null
|
||||
}
|
||||
) : null}
|
||||
{selectedJobFull.hasSideBySide && (
|
||||
<a
|
||||
title="Open side-by-side job"
|
||||
|
@ -166,9 +225,7 @@ class PerformanceTab extends React.PureComponent {
|
|||
Open side-by-side job
|
||||
</a>
|
||||
)}
|
||||
{isPerfTest(selectedJobFull) &&
|
||||
!showSideBySide &&
|
||||
!selectedJobFull.hasSideBySide && (
|
||||
{perfTest && !showSideBySide && !selectedJobFull.hasSideBySide && (
|
||||
<Button
|
||||
className="btn btn-darker-secondary btn-sm"
|
||||
onClick={this.createSideBySide}
|
||||
|
|
Загрузка…
Ссылка в новой задаче