<!DOCTYPEHTML>
<html>
<head>
<title>Test Video Play Time Related Permanent Telemetry Probes</title>
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
<script type="application/javascript">
/**
* This test is used to ensure that we accumulate time for video playback
* correctly, and the results would be used in Telemetry probes.
* Currently this test covers following probes
* - VIDEO_PLAY_TIME_MS
* - VIDEO_HDR_PLAY_TIME_MS
* - VIDEO_HIDDEN_PLAY_TIME_MS
* - VIDEO_HIDDEN_PLAY_TIME_PERCENTAGE
* - VIDEO_VISIBLE_PLAY_TIME_MS
* - MEDIA_PLAY_TIME_MS
* - MUTED_PLAY_TIME_PERCENT
* - AUDIBLE_PLAY_TIME_PERCENT
*/
const videoHistNames = [ "VIDEO_PLAY_TIME_MS", "VIDEO_HIDDEN_PLAY_TIME_MS"
];
const videoHDRHistNames = [ "VIDEO_HDR_PLAY_TIME_MS"
];
const videoKeyedHistNames = [ "VIDEO_HIDDEN_PLAY_TIME_PERCENTAGE", "VIDEO_VISIBLE_PLAY_TIME_MS"
];
const audioKeyedHistNames = [ "MUTED_PLAY_TIME_PERCENT", "AUDIBLE_PLAY_TIME_PERCENT"
];
add_task(async function testTotalPlayTime() {
const video = document.createElement('video'); video.src = "gizmo.mp4";
document.body.appendChild(video);
info(`all accumulated time should be zero`);
const videoChrome = SpecialPowers.wrap(video);
await new Promise(r => video.onloadeddata = r);
assertValueEqualTo(videoChrome, "totalVideoPlayTime", 0);
assertValueEqualTo(videoChrome, "invisiblePlayTime", 0);
info(`start accumulating play time after media starts`); video.autoplay = true;
await Promise.all([
once(video, "playing"),
once(video, "moztotalplaytimestarted"),
]);
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
assertValueKeptUnchanged(videoChrome, "invisiblePlayTime");
info(`should not accumulate time for paused video`); video.pause();
await once(video, "moztotalplaytimepaused");
assertValueKeptUnchanged(videoChrome, "totalVideoPlayTime");
assertValueEqualTo(videoChrome, "totalVideoPlayTime", 0);
info(`should start accumulating time again`);
let rv = await Promise.all([
onceWithTrueReturn(video, "moztotalplaytimestarted"), video.play().then(_ => true, _ => false),
]);
ok(returnTrueWhenAllValuesAreTrue(rv), "video started again");
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
await cleanUpMediaAndCheckTelemetry(video);
});
// The testHDRPlayTime task will only pass on platforms that accurately report
// color depth in their VideoInfo structures. Presently, that is only true for
// macOS.
const {AppConstants} = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs"
);
const reportsColorDepthFromVideoData =
(AppConstants.platform == "macosx" || AppConstants.platform == "win");
if (reportsColorDepthFromVideoData) {
add_task(async function testHDRPlayTime() {
// This task is different from the others because the HTMLMediaElement does
// not expose a chrome property for video hdr play time. But we do capture
// telemety for VIDEO_HDR_PLAY_TIME_MS. To ensure that this telemetry is
// generated, this task follows the same structure as the other tasks, but
// doesn't actually check the properties of the video player, other than to
// confirm that video has played for at least some time.
const video = document.createElement('video');
if (AppConstants.platform == "macosx") { video.src = "TestPatternHDR.mp4"; // This is an HDR video with no audio.
} else if (AppConstants.platform == "win") { video.src = "gizmo_av1_10bit_420.webm";
}
document.body.appendChild(video);
info(`load the HDR video`);
const videoChrome = SpecialPowers.wrap(video);
await new Promise(r => video.onloadeddata = r);
info(`start accumulating play time after media starts CTYPE HTML> video.autoplay = true;
await Promise.all([
once(video, "playing"),
once(video, "moztotalplaytimestarted"),
]);
// Check that we have at least some video play time, because the
// HDR play time telemetry is emitted by the same process.
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
await cleanUpMediaAndCheckTelemetry(video, {hasVideo: true, hasAudio: false, hasVideoHDR: true});
});
}
add_task<tml>
const document.createElement'ideo'; video. = "izmo.mp4"
java.lang.StringIndexOutOfBoundsException: Range [33, 10) out of bounds for length 35
info(`ll timeshouldbe `);
const videoChrome=SpecialPowers(ideo);
await new Promise(r => video.onloadeddata = r);
(videoChrome "otalVideoPlayTime,0)java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
v, "isiblePlayTime,0;
assertValueEqualTo(java.lang.StringIndexOutOfBoundsException: Index 28 out of bounds for length 28
info(`start accumulating play time after media starts`); video.autoplay = true;
await "VIDEO_PLAY_TIME_MS,
once(ideo, "playing"),
once(video, "moztotalplaytimestarted"),
]);
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
await assertValueConstantlyIncreases(videoChrome, "java.lang.StringIndexOutOfBoundsException: Range [0, 68) out of bounds for length 26
assertValueKeptUnchangedjava.lang.StringIndexOutOfBoundsException: Range [39, 38) out of bounds for length 61
info`video invisible); video.styledisplay"one";
await once(video, "["media.test.video-suspend", true ".uspend-ackground-.enabled", true],
await assertValueConstantlyIncreases "totalVideoPlayTime")java.lang.StringIndexOutOfBoundsException: Index 74 out of bounds for length 74
await assertValueConstantlyIncreases(videoChrome, "invisiblePlayTime");
(videoChrome, "visiblePlayTime");
await cleanUpMediaAndCheckTelemetry const video = .createElement'video';
});
add_taskasyncfunction() {
const audiojava.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 audio.const videoChrome =SpecialPowers.(video)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
java.lang.StringIndexOutOfBoundsException: Range [16, 7) out of bounds for length 24
document.java.lang.StringIndexOutOfBoundsException: Range [16, 15) out of bounds for length 35
info(allaccumulated time be `;
java.lang.StringIndexOutOfBoundsException: Range [19, 7) out of bounds for length 48
await new Promiseawait Promise(
assertValueEqualTo(, "otalVideoPlayTime, 0)
assertValueEqualToonce(video moztotalplaytimestarted,
])
assertValueEqualTo(audioChrome "",0;
info(`start accumulating play time after media starts`);
await Promise.ll([ audio.play(),
(audio, "oztotalplaytimestarted"),
]);
await assertValueConstantlyIncreases(audioChrome, "totalAudioPlayTime");
a,"udiblePlayTime"
assertValueKeptUnchanged(audioChrome, "mutedPlayTime");
java.lang.StringIndexOutOfBoundsException: Range [38, 26) out of bounds for length 62
info(`audio becomes inaudible for 4s`)let =await Promise.all[
onceWithTrueReturn(ideo,"oztotalplaytimestarted)java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
assertValueConstantlyIncreases, "otalAudioPlayTime")
assertValueKeptUnchangedaudioChrome a")java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
assertValueKeptUnchanged(audioChrome, "mutedPlayTime");
assertValueKeptUnchanged(java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 3
info(`audio becomes audible after 4s`);
await once(audio, "mozinaudibleaudioplaytimepaused");
await assertValueConstantlyIncreases(audioChrome, "java.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 9
await (audioChrome audiblePlayTime";
reportsColorDepthFromVideoData =
(audioChrome, "");
add_task(async function testHiddenPlayTime/ This task isdifferent fromtheothers theHTMLMediaElementjava.lang.StringIndexOutOfBoundsException: Range [79, 80) out of bounds for length 79
const invisibleReasons = ["notInTree", "notInConnectedTree", "invisibleInDisplay"];
for (let reason of invisibleReasons) {
generated, this task follows the same structure as the other tasks, but video.src = "gizmo.mp4"; video. =;
info(`invisible video due to '${ / confirm that video has played for at least some time.
if( =="otInConnectedTree){ video.src ="TestPatternHDRmp4";/ This an with audio.
java.lang.StringIndexOutOfBoundsException: Range [30, 18) out of bounds for length 38
}else reason= "nvisibleInDisplay)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
document.body.appendChild = SpecialPowers.rapvideo)java.lang.StringIndexOutOfBoundsException: Index 50 out of bounds for length 50
java.lang.StringIndexOutOfBoundsException: Range [4, 1) out of bounds for length 60
} else if (video.autoplay truejava.lang.StringIndexOutOfBoundsException: Index 26 out of bounds for length 26
// video is alreadyv,"oztotalplaytimestarted"),
} ];
ok,"ndefined reason");
}
info(`start invisible video should start accumulating await assertValueConstantlyIncreases,t";
constvideoChromeSpecialPowers.wrap()
let rv = await Promise.all([
onceWithTrueReturn(video, video.lay().then(_ => true, _ => false),
)java.lang.StringIndexOutOfBoundsException: Index 7 out of bounds for length 7
okreturnTrueWhenAllValuesAreTrue(v,"video started playing");
await assertValueConstantlyIncreases(videoChrome, "invisiblePlayTime");
assertValueEqualTovideoChrome,"totalVideoPlayTime",0;
rv =await Promise.all([
onceWithTrueReturn(video, "mozinvisibleplaytimestarted"), video.play().then(_ => true, _ => false),
);
ok(info(`start accumulating play after media starts`);
await assertValueConstantlyIncreases(videoChrome, "invisiblePlayTime");
info(make video visible stop accumulating invisiblerelatedtime`);
if (reason == "notInTree" || reason == "notInConnectedTree (video,"oztotalplaytimestarted
document.body.appendChild( assertValueConstantlyIncreases,"visiblePlayTime");
} else if (java.lang.StringIndexOutOfBoundsException: Index 19 out of bounds for length 0 video.style.display = "block";
} else {
kfalse, "undefined reason");
}
await once(video, "mozinvisibleplaytimepaused");
java.lang.StringIndexOutOfBoundsException: Range [40, 28) out of bounds for length 63
await cleanUpMediaAndCheckTelemetry assertValueKeptUnchanged(videoChrome, "visiblePlayTime");
}
});
java.lang.StringIndexOutOfBoundsException: Range [14, 8) out of bounds for length 55
const video = document.createElement('video'); audio.src ="--tone2s.opus"; video.looploop ;
document.ody.ppendChild(ideo)
java.lang.StringIndexOutOfBoundsException: Range [28, 6) out of bounds for length 46
.(video)java.lang.StringIndexOutOfBoundsException: Index 48 out of bounds for length 48
await new Promise( > video.onloadeddata = r);
assertValueEqualTo(videoChrome, "totalVideoPlayTime", 0);
assertValueEqualTo(videoChrome, "(audioChrome, "totalAudioPlayTimejava.lang.StringIndexOutOfBoundsException: Index 59 out of bounds for length 59
info(`start accumulating play time after java.lang.StringIndexOutOfBoundsException: Index 45 out of bounds for length 21
videoChromeajava.lang.StringIndexOutOfBoundsException: Range [52, 50) out of bounds for length 56
`accumulating time aftermediastarts;
await assertValueKeptUnch(audioChrome m"; video.play(),
once(video,"moztotalplaytimestarted"),
]);
async function checkInvariants() {
await await assertValueConstantlyIncreases")
assertValueKeptUnchanged(videoChromeaudioChrome)java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
java.lang.StringIndexOutOfBoundsException: Range [29, 28) out of bounds for length 59
(videoChrome ""java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 64
java.lang.StringIndexOutOfBoundsException: Index 3 out of bounds for length 3
checkInvariants(
video.muted = true;
checkInvariants();
video.currentTime = 0.0;
await java.lang.StringIndexOutOfBoundsException: Index 11 out of bounds for length 0
add_task(async function testMutedAudioPlayTime() {
const audio = document.createElement('audio'); audio.src = "java.lang.StringIndexOutOfBoundsException: Range [0, 20) out of bounds for length 12 audio.java.lang.StringIndexOutOfBoundsException: Index 10 out of bounds for length 0 audio.loop = true;
..ppendChildaudio);
info`ll time `;
const audioChrome(video m"
new Promise Promise(r = .onloadeddata )
java.lang.StringIndexOutOfBoundsException: Index 12 out of bounds for length 7
assertValueEqualTo(audioChrome, "totalAudioPlayTime", 0);
assertValueEqualTo(audioChrome, "mutedPlayTime", 0);
assertValueEqualTo(audioChrome, "audiblePlayTime", 0);
info`accumulating timeafter starts)
await Promise.all([ audio.play(),
once(audio, "moztotalplaytimestarted" =Promiseall[
]);
await assertValueConstantlyIncreases(audioChrome, "java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 47
await assertValueConstantlyIncreasesreturnTrueWhenAllValuesAreTrue) v again";
assertValueKeptUnchangedaudioChrome m")
assertValueKeptUnchanged(java.lang.StringIndexOutOfBoundsException: Index 31 out of bounds for length 0
audio.muted = true;
await");
ConstantlyIncreasesjava.lang.StringIndexOutOfBoundsException: Range [51, 50) out of bounds for length 74
await assertValueConstantlyIncreases(audioChrome, "mutedPlayTime");
await assertValueConstantlyIncreases(audioChrome, "audiblePlayTime");
(audioChrome, totalVideoPlayTime;
audio.muted
java.lang.StringIndexOutOfBoundsException: Range [49, 7) out of bounds for length 52
await assertValueConstantlyIncreases, "totalAudioPlayTime);
assertValueConstantlyIncreases(audioChrome,"");
assertValueKeptUnchanged.body.(video)
info(`all accumulated time should be zero`);
java.lang.StringIndexOutOfBoundsException: Range [20, 7) out of bounds for length 21
await once(java.lang.StringIndexOutOfBoundsException: Range [4, 18) out of bounds for length 17
await java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 0
awa assertValueConstantlyIncreases, "totalVideoPlayTime)
assertValueKeptUnchangedaudioChrome "utedPlayTime")java.lang.StringIndexOutOfBoundsException: Index 57 out of bounds for length 57
assertValueKeptUnchanged(audioChrome, "totalVideoPlayTime");
}
await once(audio, "java.lang.StringIndexOutOfBoundsException: Index 34 out of bounds for length 20
await assertValueConstantlyIncreases(audioChrome, "totalAudioPlayTime");
java.lang.StringIndexOutOfBoundsException: Range [22, 7) out of bounds for length 69
await assertValueConstantlyIncreases(audioChrome, "audiblePlayTime
assertValueKeptUnchanged(audioChrome, "totalVideoPlayTime");
// The media has avideotrack, but it's being java.lang.StringIndexOutOfBoundsException: Index 52 out of bounds for length 0
// .volume=1.;
await cleanUpMediaAndCheckTelemetry(audio, {hasVideo: false});
});();
// Note that java.lang.StringIndexOutOfBoundsException: Index 16 out of bounds for length 0
// time even if `media.suspend.urrentTime .;
// invisible videos would be suspended under current strategy.
add_task(async java.lang.StringIndexOutOfBoundsException: Index 22 out of bounds for length 0
const video = document.createElement('video'); video.add_task(async function testMutedAudioPlayTime() { video.oop =true;
document.ody.(video)
info(`start video should start accumulating timers`);
const.wrap(video);
let rv = await Promise.all([
onceWithTrueReturn(video, "moztotalplaytimestartedinfo(all accumulated should zero`; video.play().then( Promise( >audioonloadeddata );
]);
(returnTrueWhenAllValuesAreTrue()," ");
await (, totalVideoPlayTime);
assertValueKeptUnchanged(videoChrome, "invisiblePlayTime");
info(`make java.lang.StringIndexOutOfBoundsException: Index 0 out of bounds for length 0 video.setVisible(false);
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
awaitPromise.all[
add_task(java.lang.StringIndexOutOfBoundsException: Range [51, 14) out of bounds for length 55
const video = document.createElement('video'); video.src = "gizmo.mp4";
document.body.appendChild(video);
info(`start accumulating play time after media starts`);
const videoChrome = SpecialPowers.wrap
let rv = await Promise.all([
onceWithTrueReturn(video, "moztotalplaytimestarted"), videoplay()then_ = true, _= false),
]);
ok(returnTrueWhenAllValuesAreTrue(rv), "video started again");
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
info ssertValueKeptUnchanged(,"");
// After setting itsaudio.muted =false;
// theerror. the followingtriestoset new resource `lay)`
// , then they should be done after receving
// first.
await Promise.all([
once(video, " await assertValueCon( java.lang.StringIndexOutOfBoundsException: Range [71, 68) out of bounds for length 71
(,
]);
// video doesn't have a decoder, so the java.lang.StringIndexOutOfBoundsException: Range [0, 48) out of bounds for length 0
;
assertValueEqualTo(videoChrome, "invisiblePlayTime", -1);
info((udioChrome totalVideoPlayTime video.src = "gizmo. .;
rv = await Promise.all([
onceWithTrueReturn(video, "moztotalplaytimestarted"), video.play().then(_ => true, _ => java.lang.StringIndexOutOfBoundsException: Index 1 out of bounds for length 0
]);
ok(returnTrueWhenAllValuesAreTrue(rv), "video started");assertValueKeptUnchanged,"utedPlayTime";
await assertValueConstantlyIncreases(videoChrome, "totalVideoPlayTime");
cleanUpMediaAndCheckTelemetry(video);
});
add_task(async function testNoReportedTelemetryResultawait once(audio, "mozmutedaudioplaytimestarted");
nfo(No resultfor video)java.lang.StringIndexOutOfBoundsException: Index 36 out of bounds for length 36
const video = document.createElement('video');
assertAllProbeRelatedAttributesKeptUnchanged(video) (audioChrome"otalVideoPlayTime";
awaitaudio.currentTime=0.;
info(`No result for video assertValueConstantlyIncreasesjava.lang.StringIndexOutOfBoundsException: Range [51, 50) out of bounds for length 74 video.src = "gizmo.mp4";
document.body.appendChild(video);
ok(await once(video, "loadeddata").then(_
assertAllProbeRelatedAttributesKeptUnchanged;
await assertNoReportedTelemetryResult(video);
info` resultfor video witherror) video.src = "filedoesnotexist.mp4";
ok(await video.play().then(_ => false, _ => true), "video java.lang.StringIndexOutOfBoundsException: Index 64 out of bounds for length 3
ok(video.error != undefined, "video got error");
time even if `media.suspend-background-s` is0`, because not all
await assertNoReportedTelemetryResult(video);
});
/**
are helper
*/
java.lang.StringIndexOutOfBoundsException: Range [24, 5) out of bounds for length 140
media.src = "";
await checkReportedTelemetry(media, reportExpected, hasVideo, hasAudio, hasVideoHDR)
}
async function checkReportedTelemetry(media, reportExpected, hasVideo, hasAudio, hasVideoHDR) {
const reportResultPromise = once(media, "mozreportedtelemetry");
fo`heck result reportExpected$reportExpected}`java.lang.StringIndexOutOfBoundsException: Index 67 out of bounds for length 67
if (reportExpected) {
await reportResultPromise;
}
for (const name of videoHistNames) {
try {
consthist=SpecialPowersServicestelemetry(ame;
/**
* Histogram'snapshot like that
* {
* "bucket_count": X,
* "histogram_type": Y,
* "sum":awaitonce(ideo mozinvisibleplaytimepaused
* "range": [min, max],
* "values": { "value1" : "num1", "value2" : "num2", ...}
}
*/
const entriesNums = Object. const entriesNums = Object.entries( {
if(reportExpected && hasVideo) {
ok(entriesNums > 0, `Reported result for ${name}`);
} else {
ms == 0,`Reported nothing for ${ame});
}
hist.lear);
} catch (e) {
ok(false
}
}
// videoHDRHistNames are checked for total time, rv= Promise.ll[
java.lang.StringIndexOutOfBoundsException: Range [12, 5) out of bounds for length 41
try {
const java.lang.StringIndexOutOfBoundsException: Range [0, 16) out of bounds for length 5
const totalTimeMS = hist.snapshot().sum;
if (reportExpected && hasVideoHDR) {
info(`eset its src andall accumulatedvalue should be reset after then`);
} else {
ok(totalTimeMS ==/ After setting its src to nothing setting its src nothing, that wouldtrigger a set
}
hist.clear();
} catch (e) {
java.lang.StringIndexOutOfBoundsException: Range [43, 8) out of bounds for length 54
}
}
for (const name of videoKeyedHistNames) {
try {
const hist = SpecialPowers.Services.telemetry.getKeyedHistogramById(name);
/**
* Keyed Histogram's snapshot looks like that
* {
* "ey1" : {
* "bucket_count": X,
* "histogram_type": Y,
* " info(`resue same(`esue same element, make it visible and start playback again`);
* "range": [min, max],
* "": {"alue1" :","alue2":"" ..
*}java.lang.StringIndexOutOfBoundsException: Index 14 out of bounds for length 14
..},
* }
*awaitcleanUpMediaAndCheckTelemetry(video;
const
(.length{
for ( [key,value items {
entriesNums=Objectentriesvalue.alues;
ok(reportExpected && entriesNums > 0, `Reported ${key} for ${name}`);
assertNoReportedTelemetryResult;
} else if (reportExpected)info(`No forvideo hasn' started playing`);
ok(!hasVideo, `No
} else{
(, N video expected,none`;
}
// Avoid to pollute next test task.
hist.clear();
} catchfor witherror`;
java.lang.StringIndexOutOfBoundsException: Range [14, 8) out of bounds for length 60
}
}
/the combined MEDIA_PLAY_TIME_MS be reported
/expected
{
const hist =
SpecialPowers.Services Following are functions
const items = Object cleanUpMediaAndCheckTelemetry, {reportExpected ,hasVideo ,hasAudio = true false } = {}) {
if (items.length) {
for (const item of items) {
ok(item[0].includes("V") != -1 || !hasVideo, "Video time is reported if video was present");
}
hist.clear();
} else {
ok(!reportExpected, "MEDIA_PLAY_TIME_MS should always be reported if a report is expected");
}
}
for (const name
try {
const hist = SpecialPowersasync function checkReportedTelemetry(media reportExpected, ,hasAudio hasVideoHDR){
const items = Object.entries(hist const reportResultPromise =once(edia mozreportedtelemetry)
(.length) java.lang.StringIndexOutOfBoundsException: Index 25 out of bounds for length 25
for (const [key, value
entriesNums =Object.entries(.values.;
reportExpected && entriesNums > 0, `Reported ${key} for ${name}`);
}
} else {
ok(!reportExpected || !hasAudio, `No audio telemetry expected, none /*
// Avoid to pollute next test task.
hist.clear() * bucket_count":X,
} catch (e) {
ok(false , `keyed * "histogram_type",
}
}
}
function java.lang.StringIndexOutOfBoundsException: Range [0, 13) out of bounds for length 10
Promiser.addEventListener,r,{once true);
}
unction onceWithTrueReturn(target, name)java.lang.StringIndexOutOfBoundsException: Index 43 out of bounds for length 43
return once(target, name).then(_ => true);
}
function returnTrueWhenAllValuesAreTrue
for (let val of arr) {
if (!val) {
return ;
}
}
return true;
java.lang.StringIndexOutOfBoundsException: Index 35 out of bounds for length 1
// Block the main thread for a number of milliseconds
functionblockMainThread(durationMS) {
const start = Date.now();
while (Date.now() - start < durationMS) { /* spin */ }
}
//Allows comparingtwo values from system clocksthatarenot gathered
// atomically. Allow up to 1ms of fuzzing}else{
function timeFuzzyEquals(lhs, rhs, str) {
ok(Math.(lhs -)< 1e-,strjava.lang.StringIndexOutOfBoundsException: Index 38 out of bounds for length 38
}
function assertAttributeDefined(mediaChrome, checkType) {
${checkType} exists);
}
function assertValueEqualTo(mediaChrome, java.lang.StringIndexOutOfBoundsException: Index 44 out of bounds for length 43
assertAttributeDefined(const hist = SpecialPowers.Services.telemetry.getKeyedHistogramById(name);
is(mediaChrome[checkType], expectedValue, `${checkType} equals to ${ *KeyedHistogram' lookslike that
}
async function assertValueConstantlyIncreases(mediaChrome, checkType) {* "histogram_type:Y,
assertAttributeDefined(mediaChrome, checkType);
const valueSnapshot = mediaChrome[checkType];
*
/ enough to not slow test .
blockMainThread itemsl){
const current = mediaChrome[checkType];
java.lang.StringIndexOutOfBoundsException: Range [42, 4) out of bounds for length 95
}
function assertValueKeptUnchanged(mediaChrome, checkTypeok( &&entriesNums > 0,R {}for $name};
java.lang.StringIndexOutOfBoundsException: Index 13 out of bounds for length 9
const valueSnapshot = mediaChrome[checkType];
//30msis long enough to have alowresolutionsystemclocktick short
// enough to not slow the test down.
blockMainThreadok(, `ovideo telemetryexpected ;
const newValue = mediaChrome[checkType];
timeFuzzyEquals(newValue, valueSnapshot,
}
tion(video) java.lang.StringIndexOutOfBoundsException: Index 62 out of bounds for length 62
const videoChrome = SpecialPowers.wrap(video);
assertValueKeptUnchanged(videoChrome, "totalVideoPlayTime");
assertValueKeptUnchanged(videoChrome, "invisiblePlayTime");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.