Commit 08e9117f authored by Joon Ahn's avatar Joon Ahn Committed by Commit Bot

Diagnostics: Draw CPU Chart Skeleton

https://screenshot.googleplex.com/Bg8CHZ4H3aBxa54

Bug: 1125150
Change-Id: Ib28cba76d512ea40367f1906cba098fc931a531e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2461485
Commit-Queue: Joon Ahn <joonbug@chromium.org>
Reviewed-by: default avatarJimmy Gong <jimmyxgong@chromium.org>
Reviewed-by: default avatarZentaro Kavanagh <zentaro@chromium.org>
Cr-Commit-Position: refs/heads/master@{#817096}
parent e9eed233
...@@ -21,6 +21,7 @@ GEN('#include "content/public/test/browser_test.h"'); ...@@ -21,6 +21,7 @@ GEN('#include "content/public/test/browser_test.h"');
['FakeMojoInterface', 'diagnostics/mojo_interface_provider_test.js'], ['FakeMojoInterface', 'diagnostics/mojo_interface_provider_test.js'],
['FakeSystemDataProvider', 'diagnostics/fake_system_data_provider_test.js'], ['FakeSystemDataProvider', 'diagnostics/fake_system_data_provider_test.js'],
['FakeMethodProvider', 'diagnostics/fake_method_provider_test.js'], ['FakeMethodProvider', 'diagnostics/fake_method_provider_test.js'],
['RealtimeCpuChart', 'diagnostics/realtime_cpu_chart_test.js'],
['RoutineListExecutor', 'diagnostics/routine_list_executor_test.js'], ['RoutineListExecutor', 'diagnostics/routine_list_executor_test.js'],
['RoutineResultEntry', 'diagnostics/routine_result_entry_test.js'], ['RoutineResultEntry', 'diagnostics/routine_result_entry_test.js'],
['RoutineResultList', 'diagnostics/routine_result_list_test.js'], ['RoutineResultList', 'diagnostics/routine_result_list_test.js'],
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO(jimmyxgong): Use es6 module for mojo binding (crbug/1004256).
import 'chrome://resources/mojo/mojo/public/js/mojo_bindings_lite.js';
import 'chrome://diagnostics/realtime_cpu_chart.js';
import {flushTasks} from 'chrome://test/test_util.m.js';
suite('RealtimeCpuChartTest', () => {
/** @type {?HTMLElement} */
let realtimeCpuChartElement = null;
setup(() => {
PolymerTest.clearBody();
});
teardown(() => {
if (realtimeCpuChartElement) {
realtimeCpuChartElement.remove();
}
realtimeCpuChartElement = null;
});
/**
* @param {number} user
* @param {number} system
* @return {!Promise}
*/
function initializeRealtimeCpuChart(user, system) {
assertFalse(!!realtimeCpuChartElement);
// Add the element to the DOM.
realtimeCpuChartElement = document.createElement('realtime-cpu-chart');
assertTrue(!!realtimeCpuChartElement);
document.body.appendChild(realtimeCpuChartElement);
realtimeCpuChartElement.user = user;
realtimeCpuChartElement.system = system;
return flushTasks();
}
test('InitializeRealtimeCpuChart', () => {
const user = 10;
const system = 30;
return initializeRealtimeCpuChart(user, system).then(() => {
assertEquals(
`${user}`,
realtimeCpuChartElement.$$('#legend-user>span').textContent.trim());
assertEquals(
`${system}`,
realtimeCpuChartElement.$$('#legend-system>span').textContent.trim());
assertEquals(user, realtimeCpuChartElement.user);
assertEquals(system, realtimeCpuChartElement.system);
});
});
test('ChartAreaBoundary', () => {
const user = 10;
const system = 30;
return initializeRealtimeCpuChart(user, system).then(() => {
const svg = realtimeCpuChartElement.$$('#chart');
const boundary = realtimeCpuChartElement.$$('#defClip>rect');
assertGT(
Number(svg.getAttribute('width')),
Number(boundary.getAttribute('width')));
assertGT(
Number(svg.getAttribute('height')),
Number(boundary.getAttribute('height')));
});
});
});
...@@ -135,6 +135,7 @@ js_library("realtime_cpu_chart") { ...@@ -135,6 +135,7 @@ js_library("realtime_cpu_chart") {
deps = [ deps = [
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
] ]
externs_list = [ "../../../../third_party/d3/src/externs.js" ]
} }
js_library("routine_list_executor") { js_library("routine_list_executor") {
......
<style include="diagnostics-shared diagnostics-fonts"> <style include="diagnostics-shared diagnostics-fonts">
#chart-wrapper { .grid line {
width: 300px; shape-rendering: crispEdges;
border: #000 1px dotted; stroke-opacity: 0.7;
stroke: lightgrey;
} }
#chart-wrapper > div { #chart-legend {
font-size: 24px; text-align: center;
}
#chart-legend > div {
display: inline;
padding: 5px;
}
#chart-legend > div > span {
padding: 2px;
} }
</style> </style>
<div id="chart-wrapper"> <svg id="chart" width$="[[width_]]" height$="[[height_]]">
<div>[[user]]</div> <g id="chartGroup">
<div>[[system]]</div> <!-- Define chart area and boundaries -->
<defs>
<clipPath id="defClip">
<rect width$="[[graphWidth_]]" height$="[[graphHeight_]]"></rect>
</clipPath>
</defs>
<g id="gridLines" class="grid"></g>
</g>
</svg>
<div id="chart-legend">
<!-- TODO(joonbug): Localize strings, including the % -->
<div id="legend-user">
<label>User</label>
<span>[[user]]</span>
</div>
<div id="legend-system">
<label>System</label>
<span>[[system]]</span>
</div>
</div> </div>
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
import './diagnostics_fonts_css.js'; import './diagnostics_fonts_css.js';
import './diagnostics_shared_css.js'; import './diagnostics_shared_css.js';
import './d3.min.js';
import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
/** /**
...@@ -17,6 +19,12 @@ Polymer({ ...@@ -17,6 +19,12 @@ Polymer({
_template: html`{__html_template__}`, _template: html`{__html_template__}`,
/**
* Helper function to map range of y coordinates to graph height.
* @private {?d3.LinearScale}
*/
yAxisScaleFn_: null,
properties: { properties: {
user: { user: {
type: Number, type: Number,
...@@ -27,5 +35,91 @@ Polymer({ ...@@ -27,5 +35,91 @@ Polymer({
type: Number, type: Number,
value: 0, value: 0,
}, },
/** @private */
numDataPoints_: {
type: Number,
value: 50,
},
/** @private */
width_: {
type: Number,
value: 350,
},
/** @private */
height_: {
type: Number,
value: 100,
},
/** @private */
margin_: {
type: Object,
value: {top: 10, right: 20, bottom: 10, left: 30},
},
/** @private */
graphWidth_: {
readOnly: true,
type: Number,
computed: 'getGraphDimension_(width_, margin_.left, margin_.right)'
},
/** @private */
graphHeight_: {
readOnly: true,
type: Number,
computed: 'getGraphDimension_(height_, margin_.top, margin_.bottom)'
}
},
/** @override */
ready() {
this.setScaling_();
this.initializeChart_();
},
/**
* Get actual graph dimensions after accounting for margins.
* @param {number} base value of dimension.
* @param {...number} margins related to base dimension.
* @return {number}
* @private
*/
getGraphDimension_(base, ...margins) {
return margins.reduce(((acc, margin) => acc - margin), base);
},
/**
* Sets scaling functions that convert data -> svg coordinates.
* @private
*/
setScaling_() {
// Map y-values (0, 100) to (graphHeight, 0) inverse linearly.
// Data value of 0 will map to graphHeight, 100 maps to 0.
this.yAxisScaleFn_ =
d3.scaleLinear().domain([0, 100]).range([this.graphHeight_, 0]);
},
/** @private */
initializeChart_() {
const chartGroup = d3.select(this.$$('#chartGroup'));
// Position chartGroup inside the margin.
chartGroup.attr(
'transform',
'translate(' + this.margin_.left + ',' + this.margin_.top + ')');
// Draw the y-axis legend and also draw the horizontal gridlines by
// reversing the ticks back into the chart body.
chartGroup.select('#gridLines')
.call(
d3.axisLeft(/** @type {!d3.LinearScale} */(this.yAxisScaleFn_))
.ticks(3) // Number of y-axis ticks
.tickSize(-this.graphWidth_) // Extend the ticks into the
// entire graph as gridlines.
);
}, },
}); });
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment