Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
882 lines
28 KiB
JavaScript
Executable file
882 lines
28 KiB
JavaScript
Executable file
'use strict';
|
|
|
|
/* global AdvancedTelemetry, MockasyncStorage, MockNavigatorSettings, Gzip,
|
|
AdvancedTelemetryPing, MockLazyLoader */
|
|
|
|
require('/shared/js/settings_listener.js');
|
|
require('/shared/js/uuid.js');
|
|
require('/shared/js/telemetry.js');
|
|
require('/shared/test/unit/mocks/mock_navigator_moz_settings.js');
|
|
require('/shared/js/gzip/gzip.js');
|
|
requireApp('system/test/unit/mock_asyncStorage.js');
|
|
requireApp('system/js/advanced_telemetry.js');
|
|
requireApp('system/js/app_usage_metrics.js');
|
|
require('/shared/test/unit/mocks/mock_lazy_loader.js');
|
|
|
|
|
|
suite('AdvancedTelemetry:', function() {
|
|
var realMozSettings, realOnLine, realPerformanceNow;
|
|
var isOnLine = true;
|
|
var payloadOld = {
|
|
keyedHistograms: {
|
|
DEV_TOOLS_MEMORY: {
|
|
verticalhome: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type: 0,
|
|
sum: 58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
},
|
|
settings: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
}
|
|
},
|
|
DEV_TOOLS_STARTUP: {
|
|
verticalhome: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
},
|
|
settings: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
}
|
|
}
|
|
},
|
|
addonHistograms: {
|
|
addon1: {
|
|
COMM_SMS: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type: 0,
|
|
sum: 58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
|
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var payloadNew = {
|
|
keyedHistograms: {
|
|
DEV_TOOLS_MEMORY: {
|
|
verticalhome: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type: 0,
|
|
sum: 58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
},
|
|
settings: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
},
|
|
calendar: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
}
|
|
},
|
|
DEV_TOOLS_STARTUP: {
|
|
verticalhome: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
},
|
|
settings: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
}
|
|
},
|
|
DEV_TOOLS_JANK: {
|
|
verticalhome: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
},
|
|
settings: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type:0,
|
|
sum:58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]
|
|
}
|
|
}
|
|
},
|
|
addonHistograms: {
|
|
addon1: {
|
|
COMM_SMS: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type: 0,
|
|
sum: 58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
|
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
|
}
|
|
},
|
|
addon2: {
|
|
COMM_DIALER: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type: 0,
|
|
sum: 58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
|
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
var mergedPayload = {
|
|
keyedHistograms:{
|
|
DEV_TOOLS_MEMORY:{
|
|
verticalhome:{
|
|
min:1,max:1000,histogram_type:0,
|
|
sum:116,
|
|
log_sum:21.871920108795166,
|
|
log_sum_squares:59.90799617767334,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,8,0,0,0,0,0]},
|
|
settings:{
|
|
min:1,max:1000,histogram_type:0,
|
|
sum:116,
|
|
log_sum:21.871920108795166,
|
|
log_sum_squares:59.90799617767334,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,8,0,0,0,0,0]},
|
|
calendar:{
|
|
min:1,max:1000,histogram_type:0,
|
|
sum:58,
|
|
log_sum:10.935960054397583,
|
|
log_sum_squares:29.95399808883667,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]}
|
|
},
|
|
DEV_TOOLS_STARTUP:{
|
|
verticalhome:{
|
|
min:1,max:1000,histogram_type:0,
|
|
sum:116,
|
|
log_sum:21.871920108795166,
|
|
log_sum_squares:59.90799617767334,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,8,0,0,0,0,0]},
|
|
settings:{
|
|
min:1,max:1000,histogram_type:0,
|
|
sum:116,
|
|
log_sum:21.871920108795166,
|
|
log_sum_squares:59.90799617767334,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,8,0,0,0,0,0]}
|
|
},
|
|
DEV_TOOLS_JANK:{
|
|
verticalhome:{
|
|
min:1,
|
|
max:1000,histogram_type:0,
|
|
sum:58,
|
|
log_sum:10.935960054397583,
|
|
log_sum_squares:29.95399808883667,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]},
|
|
settings:{
|
|
min:1,max:1000,histogram_type:0,
|
|
sum:58,
|
|
log_sum:10.935960054397583,
|
|
log_sum_squares:29.95399808883667,
|
|
ranges:[0,1,2,5,12,29,70,170,412,1000],
|
|
counts:[0,0,0,0,4,0,0,0,0,0]}
|
|
}
|
|
},
|
|
addonHistograms:{
|
|
addon1: {
|
|
COMM_SMS: {
|
|
min: 1, max: 1000, histogram_type: 0,
|
|
sum: 116,
|
|
log_sum: 21.871920108795166,
|
|
log_sum_squares: 59.90799617767334,
|
|
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
|
counts: [0, 0, 0, 0, 8, 0, 0, 0, 0, 0]}
|
|
},
|
|
addon2: {
|
|
COMM_DIALER: {
|
|
min: 1, max: 1000, histogram_type: 0,
|
|
sum: 58,
|
|
log_sum: 10.935960054397583,
|
|
log_sum_squares: 29.95399808883667,
|
|
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
|
counts: [0, 0, 0, 0, 4, 0, 0, 0, 0, 0]}
|
|
}
|
|
}
|
|
};
|
|
|
|
function navigatorOnLine() {
|
|
return isOnLine;
|
|
}
|
|
|
|
function setNavigatorOnLine(value) {
|
|
isOnLine = value;
|
|
}
|
|
|
|
suiteSetup(function() {
|
|
realMozSettings = navigator.mozSettings;
|
|
navigator.mozSettings = MockNavigatorSettings;
|
|
window.asyncStorage = MockasyncStorage;
|
|
window.LazyLoader = MockLazyLoader;
|
|
|
|
realOnLine = Object.getOwnPropertyDescriptor(navigator, 'onLine');
|
|
Object.defineProperty(navigator, 'onLine', {
|
|
configurable: true,
|
|
get: navigatorOnLine,
|
|
set: setNavigatorOnLine
|
|
});
|
|
navigator.addIdleObserver = function(o) {
|
|
setTimeout(function() {
|
|
o.onidle();
|
|
}, o.time * 1000);
|
|
};
|
|
navigator.removeIdleObserver = function() {};
|
|
|
|
realPerformanceNow = window.performance.now;
|
|
window.performance.now = function() { return Date.now(); };
|
|
AdvancedTelemetry.DEBUG = false;
|
|
AdvancedTelemetry.LOGINFO = false;
|
|
});
|
|
|
|
suiteTeardown(function() {
|
|
navigator.mozSettings = realMozSettings;
|
|
delete window.asyncStorage;
|
|
|
|
if (realOnLine) {
|
|
Object.defineProperty(navigator, 'onLine', realOnLine);
|
|
} else {
|
|
delete navigator.onLine;
|
|
}
|
|
window.performance.now = realPerformanceNow;
|
|
});
|
|
|
|
suite('Sending the Metrics:', function() {
|
|
var at, clock, XHR, xhr, mockSettings;
|
|
var transmitSpy;
|
|
var wrapper, packedWrapper;
|
|
var gzipCompressedData = new Uint8Array([1,2,3,4,5]);
|
|
|
|
setup(function(done) {
|
|
wrapper = {
|
|
type: AdvancedTelemetry.REASON,
|
|
id: 'uuid',
|
|
creationDate: 'testDate',
|
|
version: AdvancedTelemetry.TELEMETRY_VERSION,
|
|
application: {
|
|
architecture: 'arm',
|
|
buildId: 'build',
|
|
name: AdvancedTelemetry.TELEMETRY_APP_NAME,
|
|
version: '43',
|
|
vendor: 'Mozilla',
|
|
platformVersion: '43',
|
|
xpcomAbi: 'arm-gcc3',
|
|
channel: 'default'
|
|
},
|
|
clientId: 'uuid',
|
|
payload: {
|
|
keyedHistograms: {
|
|
DEVTOOLS_HUD_REFLOW_DURATION: {
|
|
verticalhome: {
|
|
min: 1,
|
|
max: 1000,
|
|
histogram_type: 0,
|
|
sum: 189,
|
|
log_sum: 14.329224586486816,
|
|
log_sum_squares: 53.6346640586853,
|
|
ranges: [0, 1, 2, 5, 12, 29, 70, 170, 412, 1000],
|
|
counts: [0, 0, 0, 0, 2, 1, 1, 0, 0, 0]
|
|
}
|
|
}
|
|
},
|
|
addonHistograms: {
|
|
addon3: {
|
|
rn_metric: {
|
|
min: 1,
|
|
max: 10000,
|
|
histogram_type: 1,
|
|
sum: 99,
|
|
sum_squares_lo: 9801,
|
|
sum_squares_hi: 0,
|
|
ranges: [0, 1, 1251, 2501, 3751, 5001, 6250, 7500, 8750, 10000],
|
|
counts: [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
packedWrapper = {
|
|
type: AdvancedTelemetry.REASON,
|
|
id: 'uuid',
|
|
creationDate: 'testDate',
|
|
version: AdvancedTelemetry.TELEMETRY_VERSION,
|
|
application: {
|
|
architecture: 'arm',
|
|
buildId: 'build',
|
|
name: AdvancedTelemetry.TELEMETRY_APP_NAME,
|
|
version: '43',
|
|
vendor: 'Mozilla',
|
|
platformVersion: '43',
|
|
xpcomAbi: 'arm-gcc3',
|
|
channel: 'default'
|
|
},
|
|
clientId: 'uuid',
|
|
payload: {
|
|
keyedHistograms: {
|
|
DEVTOOLS_HUD_REFLOW_DURATION: {
|
|
verticalhome: {
|
|
range: [1, 1000],
|
|
bucket_count:10,
|
|
histogram_type: 0,
|
|
values: {'5':0, '12':2, '29':1, '70':1, '170':0},
|
|
sum: 189,
|
|
log_sum:14.329224586486816,
|
|
log_sum_squares: 53.6346640586853
|
|
}
|
|
}
|
|
},
|
|
addonHistograms: {
|
|
addon3: {
|
|
rn_metric: {
|
|
range: [1, 10000],
|
|
bucket_count: 10,
|
|
histogram_type: 1,
|
|
values: {'0': 0, '1': 1, '1251': 0},
|
|
sum: 99,
|
|
sum_squares_lo: 9801,
|
|
sum_squares_hi: 0
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
transmitSpy = this.sinon.spy(AdvancedTelemetry.prototype, 'transmit');
|
|
clock = this.sinon.useFakeTimers();
|
|
XHR = sinon.useFakeXMLHttpRequest();
|
|
XHR.onCreate = function(instance) { xhr = instance; };
|
|
MockNavigatorSettings.mSetup();
|
|
MockNavigatorSettings.mSyncRepliesOnly = true;
|
|
mockSettings = MockNavigatorSettings.mSettings;
|
|
this.sinon.stub(window, 'uuid', function() {
|
|
return 'uuid';
|
|
});
|
|
|
|
this.sinon.stub(Date.prototype, 'toISOString').returns('testDate');
|
|
mockSettings['deviceinfo.platform_build_id'] = 'build';
|
|
mockSettings['deviceinfo.platform_version'] = '43';
|
|
mockSettings['app.update.channel'] = 'default';
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
|
at = new AdvancedTelemetry();
|
|
at.start();
|
|
at.startCollecting();
|
|
done();
|
|
});
|
|
|
|
teardown(function() {
|
|
transmitSpy.restore();
|
|
clock.restore();
|
|
window.uuid.restore();
|
|
at.stop();
|
|
XHR.restore();
|
|
MockasyncStorage.mTeardown();
|
|
MockNavigatorSettings.mTeardown();
|
|
});
|
|
|
|
function dispatch(detail) {
|
|
window.dispatchEvent(new CustomEvent('advanced-telemetry-update',
|
|
{detail: detail}));
|
|
clock.tick();
|
|
}
|
|
|
|
test('advanced telemetry update should call transmit', function() {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
at.handleGeckoMessage(payloadNew.payload, function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
assert.equal(transmitSpy.callCount, 1);
|
|
});
|
|
});
|
|
|
|
test('should retry if not online', function(done) {
|
|
isOnLine = false;
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'startRetryBatch');
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
|
at.handleGeckoMessage(payloadNew.payload, function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startRetryBatch);
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.clearPayload);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should create the XHR properly', function(done) {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
|
|
isOnLine = true;
|
|
AdvancedTelemetryPing.prototype.send().then(function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
assert.ok(xhr);
|
|
assert.equal(xhr.method, 'POST');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should format the URL properly', function(done) {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
var deviceQuery = {
|
|
'deviceinfo.platform_version': '43',
|
|
'app.update.channel': 'default',
|
|
'deviceinfo.platform_build_id': '34'
|
|
};
|
|
|
|
var atp = new AdvancedTelemetryPing({id: '1234'}, deviceQuery);
|
|
atp.send().then(function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
// Check that the URL is properly formatted.
|
|
// URLformat:/id/reason/appName/appVersion/appUpdateChannel/appBuildID?v=4
|
|
var baseURL = AdvancedTelemetry.REPORT_URL;
|
|
assert.ok(xhr.url.indexOf(baseURL) === 0);
|
|
var path = xhr.url.substring(baseURL.length + 1).split('/');
|
|
assert.equal(path[0], '1234');
|
|
assert.equal(path[1], AdvancedTelemetry.REASON);
|
|
assert.equal(path[2], AdvancedTelemetry.TELEMETRY_APP_NAME);
|
|
assert.equal(path[3], '43');
|
|
assert.equal(path[4], 'default');
|
|
let version = path[5].split('?');
|
|
assert.equal(version[0], '34');
|
|
assert.equal(version[1], 'v=4');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should format the body properly', function(done) {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
at.handleGeckoMessage(wrapper.payload, function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
var req = JSON.parse(at.request.data);
|
|
assert.ok(req);
|
|
|
|
assert.equal(req.type, wrapper.type);
|
|
assert.equal(req.id, wrapper.id);
|
|
assert.equal(req.creationDate, wrapper.creationDate);
|
|
assert.equal(req.version, wrapper.version);
|
|
assert.equal(req.clientId, wrapper.clientId);
|
|
|
|
// Verify the application object picked up the settings correctly.
|
|
assert.deepEqual(req.application, packedWrapper.application);
|
|
// Verify that the Histograms are intact and are properly packed.
|
|
assert.deepEqual(req.payload, packedWrapper.payload);
|
|
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('advanced telemetry should gzip compression payload', function(done) {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
|
|
this.sinon.stub(AdvancedTelemetryPing.prototype, 'post', function() {
|
|
return Promise.resolve();
|
|
});
|
|
|
|
// Even though `getData` is being stubbed, since `gzip.compress` is
|
|
// stubbed to resolve compressed data, `post` should be called with
|
|
// the compressed data.
|
|
this.sinon.stub(AdvancedTelemetryPing.prototype, 'getData', function() {
|
|
return JSON.parse(JSON.stringify(wrapper.payload));
|
|
});
|
|
|
|
AdvancedTelemetryPing.prototype.send().then(function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
// `post` should be called with the compressed data
|
|
sinon.assert.calledOnce(AdvancedTelemetryPing.prototype.post);
|
|
sinon.deepEqual(
|
|
AdvancedTelemetryPing.prototype.post.getCall(0).args[1],
|
|
gzipCompressedData);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('advanced telemetry should handle gzip compression failure',
|
|
function(done) {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.reject('compress error');
|
|
});
|
|
|
|
this.sinon.stub(AdvancedTelemetryPing.prototype, 'post', function() {
|
|
return Promise.resolve();
|
|
});
|
|
|
|
// `gzip.compress` is stubbed to "reject" therefore `post` should be
|
|
// called with the original, uncompressed payload.
|
|
this.sinon.stub(AdvancedTelemetryPing.prototype, 'getData', function() {
|
|
return JSON.parse(JSON.stringify(wrapper.payload));
|
|
});
|
|
|
|
AdvancedTelemetryPing.prototype.send().then(function() {
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
// `post` should be called with the uncompressed payload
|
|
sinon.assert.calledOnce(AdvancedTelemetryPing.prototype.post);
|
|
sinon.deepEqual(
|
|
AdvancedTelemetryPing.prototype.post.getCall(0).args[1],
|
|
wrapper.payload);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should retry on a timeout error', function(done) {
|
|
var retryspy = this.sinon.spy(window, 'setTimeout');
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
this.sinon.stub(console, 'info').returns(0);
|
|
dispatch({payload: wrapper.payload});
|
|
|
|
// Simulate a timeout
|
|
xhr.ontimeout(new CustomEvent('timeout'));
|
|
assert.equal(retryspy.getCall(0).args[1],
|
|
AdvancedTelemetry.RETRY_INTERVAL);
|
|
done();
|
|
});
|
|
|
|
test('should retry interval after failed transmit', function(done) {
|
|
var retryspy = this.sinon.spy(window, 'setTimeout');
|
|
this.sinon.stub(console, 'info').returns(0);
|
|
dispatch({payload: wrapper.payload});
|
|
|
|
// Simulate a timeout
|
|
xhr.ontimeout(new CustomEvent('error'));
|
|
assert.equal(retryspy.getCall(0).args[1],
|
|
AdvancedTelemetry.RETRY_INTERVAL);
|
|
done();
|
|
});
|
|
|
|
test('should clear out the payload after a successful transmit',
|
|
function(done) {
|
|
this.sinon.stub(Gzip, 'compress', function() {
|
|
return Promise.resolve(gzipCompressedData);
|
|
});
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
|
this.sinon.stub(console, 'info').returns(0);
|
|
at.handleGeckoMessage(wrapper.payload, function() {
|
|
// Simulate a successful send
|
|
xhr.onload(new CustomEvent('load'));
|
|
MockNavigatorSettings.mReplyToRequests();
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.clearPayload);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should clear out the payload after a successful merge',
|
|
function(done) {
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
|
this.sinon.stub(console, 'info').returns(0);
|
|
at.merge = true;
|
|
at.handleGeckoMessage(wrapper.payload, function() {
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.clearPayload);
|
|
sinon.assert.calledWith(AdvancedTelemetry.prototype.clearPayload,
|
|
false);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should NOT clear out the payload after a failed transmit',
|
|
function(done) {
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
|
this.sinon.stub(console, 'info').returns(0);
|
|
at.handleGeckoMessage(wrapper.payload, function() {
|
|
// Simulate an error
|
|
xhr.ontimeout(new CustomEvent('error'));
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.clearPayload);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should NOT clear out the payload after a transmit timeout',
|
|
function(done) {
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'clearPayload');
|
|
this.sinon.stub(console, 'info').returns(0);
|
|
at.handleGeckoMessage(wrapper.payload, function() {
|
|
// Simulate a timeout
|
|
xhr.ontimeout(new CustomEvent('timeout'));
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.clearPayload);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Enable/disable:', function() {
|
|
var mockSettings, at, clock;
|
|
|
|
setup(function() {
|
|
MockNavigatorSettings.mSetup();
|
|
mockSettings = MockNavigatorSettings.mSettings;
|
|
clock = this.sinon.useFakeTimers();
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'startCollecting');
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'stopCollecting');
|
|
at = new AdvancedTelemetry();
|
|
clock.tick();
|
|
});
|
|
|
|
teardown(function() {
|
|
at.stop();
|
|
clock.tick();
|
|
MockNavigatorSettings.mTeardown();
|
|
});
|
|
|
|
test('starts immediately if enabled', function(done) {
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
|
at.start();
|
|
clock.tick();
|
|
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.stopCollecting);
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startCollecting);
|
|
done();
|
|
});
|
|
|
|
test('does not start if not enabled', function(done) {
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
|
at.start();
|
|
clock.tick();
|
|
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.stopCollecting);
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.startCollecting);
|
|
done();
|
|
});
|
|
|
|
test('starts when enabled', function(done) {
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
|
|
|
at.start();
|
|
clock.tick();
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.stopCollecting);
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.startCollecting);
|
|
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
|
MockNavigatorSettings.mTriggerObservers(
|
|
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'Enhanced' });
|
|
clock.tick();
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startCollecting);
|
|
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
|
MockNavigatorSettings.mTriggerObservers(
|
|
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'None' });
|
|
clock.tick();
|
|
|
|
done(sinon.assert.calledTwice(
|
|
AdvancedTelemetry.prototype.stopCollecting));
|
|
});
|
|
|
|
test('stops when disabled and starts again', function(done) {
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
|
at.start();
|
|
clock.tick();
|
|
sinon.assert.notCalled(AdvancedTelemetry.prototype.stopCollecting);
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.startCollecting);
|
|
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'None';
|
|
MockNavigatorSettings.mTriggerObservers(
|
|
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'None' });
|
|
clock.tick();
|
|
sinon.assert.calledOnce(AdvancedTelemetry.prototype.stopCollecting);
|
|
|
|
mockSettings[AdvancedTelemetry.TELEMETRY_ENABLED_KEY] = 'Enhanced';
|
|
MockNavigatorSettings.mTriggerObservers(
|
|
AdvancedTelemetry.TELEMETRY_ENABLED_KEY, { settingValue: 'Enhanced' });
|
|
clock.tick();
|
|
sinon.assert.calledTwice(AdvancedTelemetry.prototype.startCollecting);
|
|
done();
|
|
});
|
|
});
|
|
|
|
suite('Batch Timings:', function() {
|
|
var BatchTiming, clock;
|
|
suiteSetup(function() {
|
|
BatchTiming = AdvancedTelemetry.BatchTiming;
|
|
});
|
|
|
|
setup(function () {
|
|
clock = this.sinon.useFakeTimers();
|
|
});
|
|
|
|
test('should set full interval the first time', function (done) {
|
|
this.sinon.stub(Date, 'now').returns(2);
|
|
var bt = new BatchTiming(true);
|
|
bt.getInterval();
|
|
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY, function(value) {
|
|
assert.equal(value, '2');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should set full interval after a batch send', function (done) {
|
|
this.sinon.stub(Date, 'now').returns(2);
|
|
var bt = new BatchTiming();
|
|
bt.getInterval();
|
|
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
|
function (value) {
|
|
assert.equal(value, '2');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should not modify the start time if existing time', function (done) {
|
|
MockasyncStorage[AdvancedTelemetry.BATCH_KEY] = '2';
|
|
var bt = new BatchTiming(true);
|
|
bt.getInterval();
|
|
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
|
function (value) {
|
|
assert.equal(value, '2');
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should recalculate the interval correctly if existing time set',
|
|
function (done) {
|
|
MockasyncStorage.setItem(AdvancedTelemetry.BATCH_KEY, 1437671946520);
|
|
clock.tick();
|
|
this.sinon.stub(Date, 'now').returns(1437671946521);
|
|
|
|
var bt = new BatchTiming(true);
|
|
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
|
function (value) {
|
|
assert.equal(value, 1437671946520);
|
|
assert.equal(bt.getInterval(), 1);
|
|
done();
|
|
});
|
|
});
|
|
|
|
test('should safeguard an interval being set for too long',
|
|
function (done) {
|
|
MockasyncStorage.setItem(AdvancedTelemetry.BATCH_KEY, 1437681946521);
|
|
clock.tick();
|
|
this.sinon.stub(Date, 'now').returns(1487681946521);
|
|
|
|
var bt = new BatchTiming(true);
|
|
window.asyncStorage.getItem(AdvancedTelemetry.BATCH_KEY,
|
|
function (value) {
|
|
assert.equal(value, 1487681946521);
|
|
assert.equal(bt.getInterval(), AdvancedTelemetry.REPORT_INTERVAL);
|
|
done();
|
|
});
|
|
});
|
|
});
|
|
|
|
suite('Merging Metrics:', function() {
|
|
var mockSettings, at, clock;
|
|
// The old, and new payloads are setup to make sure that the merged
|
|
// payload properly reflects: 1) An item in the old that is not in the new,
|
|
// 2) An item in the new that is not in the old, and 3) the addition of the
|
|
// histogram elements is done correctly for sum, log_sum, and
|
|
// log_sum_squares.
|
|
|
|
setup(function() {
|
|
mockSettings = MockNavigatorSettings.mSettings;
|
|
clock = this.sinon.useFakeTimers();
|
|
this.sinon.spy(MockasyncStorage, 'setItem');
|
|
this.sinon.spy(AdvancedTelemetry.prototype, 'transmit');
|
|
at = new AdvancedTelemetry();
|
|
clock.tick();
|
|
});
|
|
|
|
teardown(function(done) {
|
|
at.stop();
|
|
clock.tick();
|
|
MockasyncStorage.mTeardown();
|
|
done();
|
|
});
|
|
|
|
test('should merge correctly with no previous metrics', function() {
|
|
at.mergeMetrics(payloadNew);
|
|
sinon.assert.calledOnce(MockasyncStorage.setItem);
|
|
// The calledWith does a deepEqual check on all the JSON elements.
|
|
sinon.assert.calledWith(MockasyncStorage.setItem,
|
|
AdvancedTelemetry.METRICS_KEY, payloadNew);
|
|
});
|
|
|
|
test('should merge correct with metrics with existing metrics', function() {
|
|
// Make a clone so we don't modify it for subsequent tests.
|
|
var cloneOldPayload = JSON.parse(JSON.stringify(payloadOld));
|
|
|
|
MockasyncStorage.setItem(AdvancedTelemetry.METRICS_KEY, cloneOldPayload);
|
|
at.mergeMetrics(payloadNew);
|
|
// Called once above for test setup.
|
|
sinon.assert.calledTwice(MockasyncStorage.setItem);
|
|
// The calledWith does a deepEqual check on all the JSON elements.
|
|
sinon.assert.calledWith(MockasyncStorage.setItem,
|
|
AdvancedTelemetry.METRICS_KEY, mergedPayload);
|
|
});
|
|
});
|
|
});
|