Added: trunk/Websites/perf.webkit.org/unit-tests/measurement-adaptor-tests.js (0 => 198463)
--- trunk/Websites/perf.webkit.org/unit-tests/measurement-adaptor-tests.js (rev 0)
+++ trunk/Websites/perf.webkit.org/unit-tests/measurement-adaptor-tests.js 2016-03-19 02:50:46 UTC (rev 198463)
@@ -0,0 +1,124 @@
+'use strict';
+
+var assert = require('assert');
+
+global.DataModelObject = require('../public/v3/models/data-model.js').DataModelObject;
+global.LabeledObject = require('../public/v3/models/data-model.js').LabeledObject;
+global.CommitLog = require('../public/v3/models/commit-log.js').CommitLog;
+global.Build = require('../public/v3/models/builder.js').Build;
+global.Builder = require('../public/v3/models/builder.js').Builder;
+global.MeasurementRootSet = require('../public/v3/models/root-set.js').MeasurementRootSet;
+global.MeasurementAdaptor = require('../public/v3/models/measurement-adaptor.js').MeasurementAdaptor;
+global.Repository = require('../public/v3/models/repository.js').Repository;
+global.RootSet = require('../public/v3/models/root-set.js').RootSet;
+global.Statistics = require('../public/shared/statistics.js');
+
+var sampleCluster = {
+ 'clusterStart': 946684800000,
+ 'clusterSize': 5184000000,
+ 'configurations': {
+ 'current': [
+ [28954983, 217.94607142857, 20, 4358.9214285714, 950303.02365434, false, [[9, '10.11 15D21', 0], [11, '192483', 1447707055576], [999, 'some unknown revision', 0]], 1447707055576, 184629, 1447762266153, '178', 176],
+ [28952257, 220.11455357143, 20, 4402.2910714286, 969099.67509885, false, [[9, '10.11 15D21', 0], [11, '192486', 1447713500460]], 1447713500460, 184614, 1447760255683, '177', 176]
+ ]
+ },
+ 'formatMap': ['id', 'mean', 'iterationCount', 'sum', 'squareSum', 'markedOutlier', 'revisions',
+ 'commitTime', 'build', 'buildTime', 'buildNumber', 'builder'],
+ 'startTime': 1449532800000,
+ 'endTime': 1454716800000,
+ 'lastModified': 1452067190008,
+ 'clusterCount': 2,
+ 'elapsedTime': 210.68406105042,
+ 'status': 'OK'
+};
+var sampleData = sampleCluster.configurations.current[0];
+
+var osx = new Repository(9, {name: 'OS X'});
+var webkit = new Repository(11, {name: 'WebKit', url: 'http://trac.webkit.org/changeset/$1'});
+var builder = new Builder(176, {name: 'WebKit Perf Builder', buildUrl: 'http://build.webkit.org/builders/$builderName/$buildNumber'});
+
+describe('MeasurementAdaptor', function () {
+ describe('applyTo', function () {
+ it('should adapt id', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ assert.equal(adoptor.applyTo(sampleData).id, 28954983);
+ });
+
+ it('should adapt mean, squareMean, and iteration count', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ assert.equal(adoptor.applyTo(sampleData).value, 217.94607142857);
+ assert.equal(adoptor.applyTo(sampleData).sum, 4358.9214285714);
+ assert.equal(adoptor.applyTo(sampleData).squareSum, 950303.02365434);
+ assert.equal(adoptor.applyTo(sampleData).iterationCount, 20);
+ });
+
+ it('should adapt commitTime as the canonical time', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ assert.equal(adoptor.applyTo(sampleData).time, 1447707055576);
+ });
+
+ it('should adapt build information as a Build object', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ assert.ok(adoptor.applyTo(sampleData).build() instanceof Build);
+ assert.equal(adoptor.applyTo(sampleData).build().id(), 184629);
+ assert.equal(adoptor.applyTo(sampleData).build().buildNumber(), '178');
+ assert.equal(adoptor.applyTo(sampleData).build().builder(), builder);
+ assert.equal(adoptor.applyTo(sampleData).build().label(), 'Build 178 on WebKit Perf Builder');
+ assert.equal(adoptor.applyTo(sampleData).build().url(), 'http://build.webkit.org/builders/WebKit Perf Builder/178');
+ });
+
+ it('should adapt revision information as a RootSet object', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ var rootSet = adoptor.applyTo(sampleData).rootSet();
+ assert.ok(rootSet instanceof RootSet);
+ assert.equal(rootSet.latestCommitTime(), 1447707055576);
+ });
+
+ it('should adapt OS X version as a CommitLog object', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ var rootSet = adoptor.applyTo(sampleData).rootSet();
+ assert.ok(rootSet instanceof RootSet);
+ assert.equal(rootSet.latestCommitTime(), 1447707055576);
+
+ assert.ok(rootSet.repositories().indexOf(osx) >= 0);
+ assert.equal(rootSet.revisionForRepository(osx), '10.11 15D21');
+
+ var commit = rootSet.commitForRepository(osx);
+ assert.ok(commit instanceof CommitLog);
+ assert.equal(commit.repository(), osx);
+ assert.ok(commit.time() instanceof Date);
+ assert.equal(commit.revision(), '10.11 15D21');
+ assert.equal(commit.label(), '10.11 15D21');
+ assert.equal(commit.title(), 'OS X at 10.11 15D21');
+ assert.equal(commit.url(), '');
+ });
+
+ it('should adapt WebKit revision as a CommitLog object', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ var rootSet = adoptor.applyTo(sampleData).rootSet();
+
+ assert.ok(rootSet.repositories().indexOf(webkit) >= 0);
+ assert.equal(rootSet.revisionForRepository(webkit), '192483');
+
+ var commit = rootSet.commitForRepository(webkit);
+ assert.ok(commit instanceof CommitLog);
+ assert.equal(commit.repository(), webkit);
+ assert.ok(commit.time() instanceof Date);
+ assert.equal(+commit.time(), 1447707055576);
+ assert.equal(commit.revision(), '192483');
+ assert.equal(commit.label(), 'r192483');
+ assert.equal(commit.title(), 'WebKit at r192483');
+ assert.equal(commit.url(), 'http://trac.webkit.org/changeset/192483');
+ });
+
+ it('should not create separate CommitLog object for the same revision', function () {
+ var adoptor = new MeasurementAdaptor(sampleCluster.formatMap);
+ assert.equal(adoptor.applyTo(sampleData).rootSet().commitForRepository(webkit),
+ adoptor.applyTo(sampleData).rootSet().commitForRepository(webkit));
+
+ assert.equal(adoptor.applyTo(sampleData).rootSet().commitForRepository(osx),
+ adoptor.applyTo(sampleData).rootSet().commitForRepository(osx));
+ });
+
+ });
+});
\ No newline at end of file
Added: trunk/Websites/perf.webkit.org/unit-tests/measurement-set-tests.js (0 => 198463)
--- trunk/Websites/perf.webkit.org/unit-tests/measurement-set-tests.js (rev 0)
+++ trunk/Websites/perf.webkit.org/unit-tests/measurement-set-tests.js 2016-03-19 02:50:46 UTC (rev 198463)
@@ -0,0 +1,445 @@
+'use strict';
+
+var assert = require('assert');
+
+global.DataModelObject = require('../public/v3/models/data-model.js').DataModelObject;
+global.LabeledObject = require('../public/v3/models/data-model.js').LabeledObject;
+global.CommitLog = require('../public/v3/models/commit-log.js').CommitLog;
+global.Build = require('../public/v3/models/builder.js').Build;
+global.Builder = require('../public/v3/models/builder.js').Builder;
+global.MeasurementRootSet = require('../public/v3/models/root-set.js').MeasurementRootSet;
+global.MeasurementAdaptor = require('../public/v3/models/measurement-adaptor.js').MeasurementAdaptor;
+global.MeasurementCluster = require('../public/v3/models/measurement-cluster.js').MeasurementCluster;
+global.MeasurementSet = require('../public/v3/models/measurement-set.js').MeasurementSet;
+global.Repository = require('../public/v3/models/repository.js').Repository;
+global.RootSet = require('../public/v3/models/root-set.js').RootSet;
+global.Statistics = require('../public/shared/statistics.js');
+
+if (!assert.notReached)
+ assert.notReached = function () { assert(false, 'This code path should not be reached'); }
+
+var requests = [];
+
+global.RemoteAPI = {
+ getJSON: function ()
+ {
+ assert.notReached();
+ },
+ getJSONWithStatus: function (url)
+ {
+ var request = {
+ url: url,
+ promise: null,
+ resolve: null,
+ reject: null,
+ };
+
+ request.promise = new Promise(function (resolve, reject) {
+ request.resolve = resolve;
+ request.reject = reject;
+ });
+
+ requests.push(request);
+ return request.promise;
+ },
+};
+
+describe('MeasurementSet', function () {
+ describe('findSet', function () {
+ it('should create a new MeasurementSet for a new pair of platform and matric', function () {
+ assert.notEqual(MeasurementSet.findSet(1, 1, 3000), MeasurementSet.findSet(1, 2, 3000));
+ assert.notEqual(MeasurementSet.findSet(1, 1, 3000), MeasurementSet.findSet(2, 1, 3000));
+ });
+
+ it('should not create a new MeasurementSet when the same pair of platform and matric are requested', function () {
+ assert.equal(MeasurementSet.findSet(1, 1), MeasurementSet.findSet(1, 1));
+ });
+ });
+
+ describe('fetchBetween', function () {
+ beforeEach(function () {
+ requests = [];
+ MeasurementSet._set = null;
+ });
+
+ it('should always request the cached primary cluster first', function () {
+ var set = MeasurementSet.findSet(1, 1, 3000);
+ set.fetchBetween(1000, 2000, function () { assert.notReached(); });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+ });
+
+ it('should not request the cached primary cluster twice', function () {
+ var set = MeasurementSet.findSet(1, 1, 3000);
+ set.fetchBetween(1000, 2000, function () { assert.notReached(); });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+ set.fetchBetween(2000, 3000, function () { assert.notReached(); });
+ assert.equal(requests.length, 1);
+ });
+
+ it('should invoke the callback when the up-to-date cached primary cluster is fetched and it matches the requested range', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 3000);
+ var callCount = 0;
+ set.fetchBetween(2000, 3000, function () {
+ callCount++;
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 2000,
+ 'endTime': 3000,
+ 'lastModified': 3000,
+ 'clusterCount': 2,
+ 'status': 'OK'});
+
+ requests[0].promise.then(function () {
+ assert.equal(callCount, 1);
+ assert.equal(requests.length, 1);
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should invoke the callback and fetch a secondary cluster'
+ + 'when the cached primary cluster is up-to-date and within in the requested range', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 3000);
+ var callCount = 0;
+ set.fetchBetween(1000, 3000, function () {
+ callCount++;
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 2000,
+ 'endTime': 3000,
+ 'lastModified': 3000,
+ 'clusterCount': 2,
+ 'status': 'OK'});
+
+ Promise.resolve().then(function () {
+ assert.equal(callCount, 1);
+ assert.equal(requests.length, 2);
+ assert.equal(requests[1].url, '../data/measurement-set-1-1-2000.json');
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should request additional secondary clusters as requested', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 5000);
+ set.fetchBetween(2000, 3000, function () {
+ assert.notReached();
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 4000,
+ 'endTime': 5000,
+ 'lastModified': 5000,
+ 'clusterCount': 3,
+ 'status': 'OK'});
+
+ Promise.resolve().then(function () {
+ assert.equal(requests.length, 2);
+ assert.equal(requests[1].url, '../data/measurement-set-1-1-3000.json');
+
+ var callCount = 0;
+ set.fetchBetween(0, 7000, function () { callCount++; });
+
+ assert.equal(callCount, 1);
+ assert.equal(requests.length, 4);
+ assert.equal(requests[2].url, '../data/measurement-set-1-1-2000.json');
+ assert.equal(requests[3].url, '../data/measurement-set-1-1-4000.json');
+
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should request secondary clusters which forms a superset of the requested range', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 5000);
+ set.fetchBetween(2707, 4207, function () {
+ assert.notReached();
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 4000,
+ 'endTime': 5000,
+ 'lastModified': 5000,
+ 'clusterCount': 3,
+ 'status': 'OK'});
+
+ Promise.resolve().then(function () {
+ assert.equal(requests.length, 3);
+ assert.equal(requests[1].url, '../data/measurement-set-1-1-3000.json');
+ assert.equal(requests[2].url, '../data/measurement-set-1-1-4000.json');
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should not request secondary clusters that are not requested', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 5000);
+ set.fetchBetween(3200, 3700, function () {
+ assert.notReached();
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 4000,
+ 'endTime': 5000,
+ 'lastModified': 5000,
+ 'clusterCount': 3,
+ 'status': 'OK'});
+
+ Promise.resolve().then(function () {
+ assert.equal(requests.length, 2);
+ assert.equal(requests[1].url, '../data/measurement-set-1-1-4000.json');
+
+ var callCount = 0;
+ set.fetchBetween(1207, 1293, function () { callCount++; });
+
+ assert.equal(callCount, 0);
+ assert.equal(requests.length, 3);
+ assert.equal(requests[2].url, '../data/measurement-set-1-1-2000.json');
+
+ set.fetchBetween(1964, 3401, function () { callCount++; });
+
+ assert.equal(callCount, 0);
+ assert.equal(requests.length, 4);
+ assert.equal(requests[3].url, '../data/measurement-set-1-1-3000.json');
+
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should invoke the callback when the fetching of the primray cluster fails', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 3000);
+ var callCount = 0;
+ set.fetchBetween(1000, 3000, function () {
+ callCount++;
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].reject(500);
+
+ Promise.resolve().then(function () {
+ assert.equal(callCount, 1);
+ assert.equal(requests.length, 1);
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should request the uncached primary cluster when the cached cluster is outdated', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 3005);
+ var callCount = 0;
+ set.fetchBetween(1000, 2000, function () {
+ callCount++;
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 2000,
+ 'endTime': 3000,
+ 'lastModified': 3000,
+ 'clusterCount': 2,
+ 'status': 'OK'});
+
+ Promise.resolve().then(function () {
+ assert.equal(callCount, 0);
+ assert.equal(requests.length, 2);
+ assert.equal(requests[1].url, '../api/measurement-set?platform=1&metric=1');
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should request the uncached primary cluster when the cached cluster is 404', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 3005);
+ var callCount = 0;
+ set.fetchBetween(1000, 2000, function () {
+ callCount++;
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].reject(404);
+
+ Promise.resolve().then(function () {
+ assert.equal(callCount, 0);
+ assert.equal(requests.length, 2);
+ assert.equal(requests[1].url, '../api/measurement-set?platform=1&metric=1');
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should not request the primary cluster twice when multiple clients request it but should invoke all callbacks', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 3000);
+ var callCount = 0;
+ set.fetchBetween(2000, 3000, function () {
+ callCount++;
+ });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ var alternativeCallCount = 0;
+ set.fetchBetween(2000, 3000, function () {
+ alternativeCallCount++;
+ });
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 2000,
+ 'endTime': 3000,
+ 'lastModified': 3000,
+ 'clusterCount': 2,
+ 'status': 'OK'});
+
+ Promise.resolve().then(function () {
+ assert.equal(callCount, 1);
+ assert.equal(alternativeCallCount, 1);
+ assert.equal(requests.length, 1);
+ done();
+ }).catch(function (error) {
+ done(error);
+ });
+ });
+
+ it('should invoke callback for each secondary clusters that are fetched or rejected', function (done) {
+ var set = MeasurementSet.findSet(1, 1, 5000);
+ var callCountFor4000 = 0;
+ set.fetchBetween(3200, 3700, function () { callCountFor4000++; });
+ assert.equal(requests.length, 1);
+ assert.equal(requests[0].url, '../data/measurement-set-1-1.json');
+
+ requests[0].resolve({
+ 'clusterStart': 1000,
+ 'clusterSize': 1000,
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 4000,
+ 'endTime': 5000,
+ 'lastModified': 5000,
+ 'clusterCount': 3,
+ 'status': 'OK'});
+
+ var callCountFor4000To5000 = 0;
+ var callCountFor2000 = 0;
+ var callCountFor2000To4000 = 0;
+ Promise.resolve().then(function () {
+ assert.equal(callCountFor4000, 0);
+ assert.equal(requests.length, 2);
+ assert.equal(requests[1].url, '../data/measurement-set-1-1-4000.json');
+
+ set.fetchBetween(3708, 4800, function () { callCountFor4000To5000++; });
+ assert.equal(callCountFor4000To5000, 1);
+ assert.equal(requests.length, 2);
+
+ set.fetchBetween(1207, 1293, function () { callCountFor2000++; });
+ assert.equal(callCountFor2000, 0);
+ assert.equal(requests.length, 3);
+ assert.equal(requests[2].url, '../data/measurement-set-1-1-2000.json');
+
+ requests[2].resolve({
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 1000,
+ 'endTime': 2000,
+ 'lastModified': 5000,
+ 'status': 'OK'});
+ }).then(function () {
+ assert.equal(requests.length, 3);
+ assert.equal(callCountFor4000, 0);
+ assert.equal(callCountFor4000To5000, 1);
+ assert.equal(callCountFor2000, 1);
+
+ set.fetchBetween(1964, 3401, function () { callCountFor2000To4000++; });
+
+ assert.equal(callCountFor2000To4000, 1);
+ assert.equal(requests.length, 4);
+ assert.equal(requests[3].url, '../data/measurement-set-1-1-3000.json');
+
+ requests[3].resolve({
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 2000,
+ 'endTime': 3000,
+ 'lastModified': 5000,
+ 'status': 'OK'});
+ }).then(function () {
+ assert.equal(callCountFor4000, 0);
+ assert.equal(callCountFor4000To5000, 1);
+ assert.equal(callCountFor2000, 1);
+ assert.equal(callCountFor2000To4000, 2);
+ assert.equal(requests.length, 4);
+
+ requests[1].resolve({
+ 'formatMap': [],
+ 'configurations': {current: []},
+ 'startTime': 3000,
+ 'endTime': 4000,
+ 'lastModified': 5000,
+ 'status': 'OK'});
+ }).then(function () {
+ assert.equal(callCountFor4000, 1);
+ assert.equal(callCountFor4000To5000, 2);
+ assert.equal(callCountFor2000, 1);
+ assert.equal(callCountFor2000To4000, 3);
+ assert.equal(requests.length, 4);
+
+ done();
+ }).catch(function (error) {
+ done(error);
+ })
+ });
+
+ });
+
+});
\ No newline at end of file