// Copyright (c) Microsoft Corporation. All Rights Reserved. Licensed under the MIT License. See License.txt in the project root for license information. // /// /// /// declare var Debug; module CorsicaTests { "use strict"; var lvUnhandledErrors = {}; function errorEventHandler(evt) { var details = evt.detail; var id = details.id; if (!details.parent) { lvUnhandledErrors[id] = details; } else if (details.handler) { delete lvUnhandledErrors[id]; } } function initUnhandledErrors() { lvUnhandledErrors = {}; WinJS.Promise.addEventListener("error", errorEventHandler); } function validateUnhandledErrors() { WinJS.Promise.removeEventListener("error", errorEventHandler); LiveUnit.Assert.areEqual(0, Object.keys(lvUnhandledErrors).length, "Unhandled errors found"); } export class AsyncCausalityChain { OperationStarting: any[]; OperationCompleted: any[]; CallbackStarting: any[]; CallbackCompleted: any[]; realTraceAsyncOperationStarting; realTraceAsyncOperationCompleted; realTraceAsyncCallbackStarting; realTraceAsyncCallbackCompleted; setUp() { this.OperationStarting = []; this.OperationCompleted = []; this.CallbackStarting = []; this.CallbackCompleted = []; this.realTraceAsyncOperationStarting = WinJS.Utilities._traceAsyncOperationStarting; this.realTraceAsyncOperationCompleted = WinJS.Utilities._traceAsyncOperationCompleted; this.realTraceAsyncCallbackStarting = WinJS.Utilities._traceAsyncCallbackStarting; this.realTraceAsyncCallbackCompleted = WinJS.Utilities._traceAsyncCallbackCompleted; WinJS.Utilities._require(['WinJS/Core/_Trace'], (_Trace) => { _Trace._traceAsyncOperationStarting = (name) => { this.OperationStarting.push({ id: this.OperationStarting.length, name: name }); return this.OperationStarting.length - 1; }; _Trace._traceAsyncOperationCompleted = (id, status) => { this.OperationCompleted.push({ id: id, status: status }); }; _Trace._traceAsyncCallbackStarting = (id) => { this.CallbackStarting.push({ id: id }); }; _Trace._traceAsyncCallbackCompleted = () => { this.CallbackCompleted.push({}); }; }); } tearDown() { WinJS.Utilities._require(['WinJS/Core/_Trace'], (_Trace) => { _Trace._traceAsyncOperationStarting = this.realTraceAsyncOperationStarting; _Trace._traceAsyncOperationCompleted = this.realTraceAsyncOperationCompleted; _Trace._traceAsyncCallbackStarting = this.realTraceAsyncCallbackStarting; _Trace._traceAsyncCallbackCompleted = this.realTraceAsyncCallbackCompleted; }); } verify(expected) { if (expected.opStartingCount !== undefined && expected.opStartingCount >= 0) { LiveUnit.Assert.areEqual(expected.opStartingCount, this.OperationStarting.length); } if (expected.opCompletedCount !== undefined && expected.opCompletedCount >= 0) { LiveUnit.Assert.areEqual(expected.opCompletedCount, this.OperationCompleted.length); } if (expected.callbackStartingCount !== undefined && expected.callbackStartingCount >= 0) { LiveUnit.Assert.areEqual(expected.callbackStartingCount, this.CallbackStarting.length); } if (expected.callbackCompletedCount !== undefined && expected.callbackCompletedCount >= 0) { LiveUnit.Assert.areEqual(expected.callbackCompletedCount, this.CallbackCompleted.length); } } testSchedulerSchedule(complete) { var job = WinJS.Utilities.Scheduler.schedule((jobInfo) => { this.verify({ opStartingCount: 1, opCompletedCount: 0, callbackStartingCount: 1 }); LiveUnit.Assert.areEqual(0, this.CallbackStarting[0].id); WinJS.Utilities._setImmediate(() => { this.verify({ opStartingCount: 1, opCompletedCount: 1, callbackStartingCount: 1, callbackCompletedCount: 1 }); LiveUnit.Assert.areEqual(0, this.OperationCompleted[0].id); LiveUnit.Assert.areEqual(Debug.MS_ASYNC_OP_STATUS_SUCCESS, this.OperationCompleted[0].status); complete(); }); }); this.verify({ opStartingCount: 1 }); LiveUnit.Assert.areEqual("WinJS.Utilities.Scheduler.schedule: " + job.id, this.OperationStarting[0].name) } testSchedulerCancel() { var job = WinJS.Utilities.Scheduler.schedule(function (jobInfo) { }); this.verify({ opStartingCount: 1 }); job.cancel(); this.verify({ opStartingCount: 1, opCompletedCount: 1 }); LiveUnit.Assert.areEqual((job)._asyncOpID, this.OperationCompleted[0].id); LiveUnit.Assert.areEqual(Debug.MS_ASYNC_OP_STATUS_CANCELED, this.OperationCompleted[0].status); } testPromiseThen(complete) { var p = new WinJS.Promise(function (c, e, p) { WinJS.Utilities._setImmediate(c); }); p.then(() => { this.verify({ opStartingCount: 1, opCompletedCount: 1, callbackStartingCount: 1 }); LiveUnit.Assert.areEqual("WinJS.Promise.then", this.OperationStarting[0].name) LiveUnit.Assert.areEqual(Debug.MS_ASYNC_OP_STATUS_SUCCESS, this.OperationCompleted[0].status); LiveUnit.Assert.areEqual(0, this.OperationCompleted[0].id); LiveUnit.Assert.areEqual(0, this.CallbackStarting[0].id); }); this.verify({ opStartingCount: 1 }); WinJS.Utilities._setImmediate(() => { this.verify({ opStartingCount: 1, opCompletedCount: 1, callbackStartingCount: 1, callbackCompletedCount: 1 }); complete(); }); } testPromiseInitError(complete) { initUnhandledErrors(); var p = new WinJS.Promise(function (c, e, p) { WinJS.Utilities._setImmediate(e); }); p.then(null, () => { this.verify({ opStartingCount: 1, opCompletedCount: 1, callbackStartingCount: 1 }); LiveUnit.Assert.areEqual(Debug.MS_ASYNC_OP_STATUS_ERROR, this.OperationCompleted[0].status); LiveUnit.Assert.areEqual(0, this.OperationCompleted[0].id); LiveUnit.Assert.areEqual(0, this.CallbackStarting[0].id); }); this.verify({ opStartingCount: 1 }); WinJS.Utilities._setImmediate(() => { this.verify({ opStartingCount: 1, opCompletedCount: 1, callbackStartingCount: 1, callbackCompletedCount: 1 }); validateUnhandledErrors(); complete(); }); } testPromiseCancel(complete) { var p = new WinJS.Promise(function (c, e, p) { WinJS.Utilities._setImmediate(c); }); p.then(null, function () { }); this.verify({ opStartingCount: 1 }); p.cancel(); WinJS.Utilities._setImmediate(() => { this.verify({ opStartingCount: 1, opCompletedCount: 1, callbackStartingCount: 1, callbackCompletedCount: 1 }); complete(); }); LiveUnit.Assert.areEqual(Debug.MS_ASYNC_OP_STATUS_CANCELED, this.OperationCompleted[0].status); LiveUnit.Assert.areEqual(0, this.OperationCompleted[0].id); LiveUnit.Assert.areEqual(0, this.CallbackStarting[0].id); } testSchedulerJobWithYield(complete) { var that = this; var i = 0; var jobCompleted = null; var p = new WinJS.Promise(function (c) { jobCompleted = c; }); var work = (jobInfo) => { this.verify({ opCompletedCount: 0, callbackStartingCount: 1 + i, callbackCompletedCount: 0 + i }); if (i++ < 3) { jobInfo.setWork(work); } else { jobCompleted(); } }; var job = WinJS.Utilities.Scheduler.schedule(work); p.then(function () { LiveUnit.Assert.areEqual(1, that.OperationCompleted.length); LiveUnit.Assert.areEqual(Debug.MS_ASYNC_OP_STATUS_SUCCESS, that.OperationCompleted[0].status); complete(); }); } }; } if ((window).Debug && Debug.msTraceAsyncCallbackStarting) { LiveUnit.registerTestClass("CorsicaTests.AsyncCausalityChain"); }