• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16class Test {
17    private static UNSET: int = 0;
18    private static SUCCESS: int = 1;
19
20    constructor(iterations: int = 0) {
21        this.result = Test.UNSET;
22        this.iterations = iterations;
23    }
24
25    success(): void {
26        if (this.result == Test.UNSET) {
27            this.result = Test.SUCCESS;
28        }
29    }
30
31    fail(): void {
32        console.println("Test failed");
33        throw new Error();
34    }
35
36    check(): void {
37        if (this.result == Test.SUCCESS) {
38            return;
39        }
40        if (this.result == Test.UNSET) {
41            console.println("Test result is not set");
42        }
43        throw new Error();
44    }
45
46    ready(): boolean {
47        if (this.iterations == 0) {
48            return true;
49        }
50        this.iterations--;
51        return false;
52    }
53
54    static FATAL: int = 0;
55    static ERROR: int = 1;
56    static INFO: int = 2;
57    // private log_level: int = 5;
58    private log_level: int = 1;
59
60    setLogLevel(lvl: int): void {
61        this.log_level = lvl;
62    }
63
64    msg(s: String, lvl: int): void {
65        if (lvl <= this.log_level) {
66            console.println(s);
67        }
68    }
69
70    private result: int;
71    private iterations: int;
72}
73let globalTest: Test | null = null;
74
75function check(): int {
76    globalTest!.check();
77    return 0;
78}
79
80function ready(): boolean {
81    return globalTest!.ready();
82}
83
84function testPendingPromise(): int {
85    globalTest = new Test();
86    let p = new Promise<Object>((resolve: (value: Object) => void): void => {
87        globalTest!.success()
88    });
89    globalTest!.check();
90    p.then<void>((): void => {
91        globalTest!.fail();
92    });
93    p.catch<void>((error: NullishType): void => {
94        globalTest!.fail();
95    });
96    // Check callback are not called inside 'then' and 'catch'
97    globalTest!.check();
98    return 0;
99}
100
101function testResolvedPromise(): int {
102    let obj = new Object();
103    let p = new Promise<Object>((resolve: (value: Object) => void): void => {
104        resolve(obj);
105    });
106    globalTest = new Test();
107    p.then<Object | null>((value: Object): Object | null => {
108        if (value == obj) {
109            globalTest!.success();
110        } else {
111            globalTest!.fail();
112        }
113        return null;
114    });
115    p.catch<Object | null>((err: NullishType): Object | null => {
116        globalTest!.fail();
117        return null;
118    });
119    return 0;
120}
121
122function testRejectedPromise(): int {
123    globalTest = new Test();
124    let error = new Error();
125    try {
126        let p = new Promise<Object>((resolve: (value: Object) => void): void => {
127            throw error;
128        });
129        p.then<Object | null>((value: Object): Object | null => {
130            globalTest!.fail();
131            return null;
132        });
133        p.catch<Object | null>((err: NullishType): Object => {
134            if (err == error) {
135                globalTest!.success();
136            } else {
137                globalTest!.fail();
138            }
139        });
140    } catch (e: Exception) {
141        globalTest!.fail();
142    }
143    return 0;
144}
145
146class ThenBeforeResolveFixture {
147    public fn: (value: Object) => void = (value: Object) => {};
148    public state = 0;
149}
150
151function testThenBeforeResolve(): int {
152    globalTest = new Test();
153    let fixture = new ThenBeforeResolveFixture();
154    let p = new Promise<Object>((resolve: (value: Object) => void): void => {
155        fixture.fn = resolve;
156    });
157    let obj = new Object();
158    p.then<Object | null>((value: Object): Object | null => {
159        if (value == obj) {
160            if (fixture.state == 0) {
161                fixture.state = 1;
162            } else {
163                console.println("Wrong 'then' call order");
164                globalTest!.fail();
165            }
166        } else {
167            console.println("Then is called with wrong object");
168            globalTest!.fail();
169        }
170        return null;
171    });
172    p.then<Object | null>((value: Object): Object | null => {
173        if (value == obj) {
174            if (fixture.state == 1) {
175                globalTest!.success();
176            } else {
177                console.println("Wrong 'then' call order");
178                globalTest!.fail();
179            }
180        } else {
181            console.println("Then is called with wrong object");
182            globalTest!.fail();
183        }
184        return null;
185    });
186    fixture.fn(obj);
187    return 0;
188}
189
190function testPromiseEmptyThen(): int {
191    globalTest = new Test();
192    let p = new Promise<Object>((resolve: (value: Object) => void): void => {
193        resolve(new Object());
194    });
195    let nextP = p.then<Object>((): Object => {
196        globalTest!.success();
197    });
198    return 0;
199}
200
201class PromiseChainFixture {
202    public state = 0;
203}
204
205function testPromiseChain(): int {
206    globalTest = new Test(2);
207    let fixture = new PromiseChainFixture();
208    let p = new Promise<Object>((resolve: (value: Object) => void): void => {
209        resolve(new Object());
210    });
211    // NOTE(audovichenko): Remove p1 and p2 variables #17359
212    let p1: Promise<void> = p.then<void>((): void => {
213        if (fixture.state == 0) {
214            fixture.state = 1;
215        } else {
216            globalTest!.fail();
217        }
218    });
219    let p2: Promise<void> = p1.then<void>((): void => {
220        if (fixture.state == 1) {
221            fixture.state = 2;
222        } else {
223            globalTest!.fail();
224        }
225    });
226    p2.then<void>((): void => {
227        if (fixture.state == 2) {
228            globalTest!.success();
229        } else {
230            globalTest!.fail();
231        }
232    });
233    return 0;
234}
235
236function testPromiseCatchFinallyChain(): int {
237    globalTest = new Test(2);
238    let fixture = new PromiseChainFixture();
239    let p: Promise<Object> = Promise.reject<Object>(new Object());
240    // NOTE(audovichenko): Remove p1 and p2 variables #17359
241    let p1: Promise<void> = p.then<void>((v: Object): void => {
242        globalTest!.fail();
243    });
244    let p2: Promise<void> = p1.catch<void>((value: NullishType): void => {
245        if (fixture.state == 0) {
246            fixture.state = 1;
247        } else {
248            globalTest!.fail();
249        }
250    });
251    p2.finally((): void => {
252        if (fixture.state == 1) {
253            globalTest!.success();
254        } else {
255            globalTest!.fail();
256        }
257    });
258    return 0;
259}
260
261function testResolvePromiseThenFinally(): int {
262    globalTest = new Test(1);
263    let fixture = new PromiseChainFixture();
264    let p = Promise.resolve<Object>(new Object());
265    // NOTE(audovichenko): Remove p1 and p2 variables #17359
266    let p1: Promise<void> = p.then<void, void>((value: Object): void => {
267        if (fixture.state == 0) {
268            fixture.state = 1;
269        } else {
270            globalTest!.fail();
271        }
272    }, (error: NullishType): void => {
273        globalTest!.fail();
274    });
275    p1.finally((): void => {
276        if (fixture.state == 1) {
277            globalTest!.success();
278        } else {
279            globalTest!.fail();
280        }
281    });
282    return 0;
283}
284
285function testRejectPromiseThenFinally(): int {
286    globalTest = new Test(1);
287    let fixture = new PromiseChainFixture();
288    let p = Promise.reject<Object>(new Object());
289    // NOTE(audovichenko): Remove p1 and p2 variables #17359
290    let p1: Promise<void> = p.then<void, void>((value: Object): void => {
291        globalTest!.fail();
292    }, (error: NullishType): void => {
293        if (fixture.state == 0) {
294            fixture.state = 1;
295        } else {
296            globalTest!.fail();
297        }
298    });
299    p1.finally((): void => {
300        if (fixture.state == 1) {
301            globalTest!.success();
302        } else {
303            globalTest!.fail();
304        }
305    });
306    return 0;
307}
308
309function testReturnPromise(): Promise<Object> {
310    return new Promise<Object>((resolve: (value: Object) => void): void => {
311        resolve("Panda");
312    });
313}
314
315async function testReturnPromiseFromAsync(): Promise<Object> {
316    return new Promise<Object>((resolve: (value: Object) => void): void => {
317        resolve("Panda");
318    });
319}
320
321let resolvePromiseFn: ((value: Object) => void) | null = null;
322
323function testReturnPendingPromise(): Promise<Object> {
324    return new Promise<Object>((resolve: (value: Object) => void): void => {
325        resolvePromiseFn = resolve;
326    });
327}
328
329function resolvePendingPromise(): boolean {
330    if (resolvePromiseFn == null) {
331        return false;
332    }
333    (resolvePromiseFn as (value: Object) => void)("Panda");
334    return true;
335}
336
337let unresolved1: Object | null = null;
338let unresolved2: Object | null = null;
339
340async function asyncFuncAwait(): Promise<Object | null> {
341    let promise: Promise<Object> = new Promise<Object>((resolve: (obj: Object) => void): void => {
342        resolve("resolved");
343    });
344    unresolved1 = await promise;
345    return null;
346}
347
348let asyncLambdaAwait: () => Promise<Object | null> = async (): Promise<Object | null> => {
349    let promise: Promise<Object> = new Promise<Object>((resolve: (obj: Object) => void): void => {
350        resolve("resolved");
351    });
352    unresolved2 = await promise;
353    return null;
354}
355
356function testAwaitPromise(): int {
357    globalTest = new Test();
358    let p1: Promise<Object | null> = asyncFuncAwait();
359    let p2: Promise<Object | null> = asyncLambdaAwait();
360    if (unresolved1 != "resolved" || unresolved2 != "resolved") {
361        globalTest!.fail();
362    }
363    globalTest!.success();
364    return 0;
365}
366
367function makeResolvedPromise(v: String): Promise<Object> {
368    return new Promise<Object>((resolve: (value: Object) => void): void => {
369        resolve(v);
370    });
371}
372
373async function testAwaitJsPromise(pendingP: Promise<Object>): Promise<Object> {
374    globalTest = new Test();
375
376    globalTest!.msg("testAwaitJsPromise: start", Test.INFO);
377    let res: String = (await pendingP) as String;
378
379    globalTest!.msg("testAwaitJsPromise: await result is: " + res, Test.INFO);
380
381    if (res != "JS_PROMISE_RESULT") {
382        globalTest!.msg("testAwaitJsPromise: await result is wrong!", Test.FATAL);
383        globalTest!.fail();
384    } else {
385        globalTest!.msg("testAwaitJsPromise: await result is CORRECT!", Test.INFO);
386        globalTest!.success();
387    }
388
389    globalTest!.msg("testAwaitJsPromise: done", Test.INFO);
390    /**
391     * NOTE(konstanting, #I67QXC): add a test where we would return here a PENDING promise.
392     * Currently this leads to a crash, because:
393     *     - testAwaitJsPromise$asyncImpl resolves its linked promise (P1) with makeResolvedPromise's result (P2)
394     *     - since we returned P1 to JS as PENDING (due to await presence), it has listeners
395     *     - thus, P1 resolution triggers PandaEtsVM::FirePromiseStateChanged, which acquires promise_listeners_lock_
396     *     - this leads to wrapping P1's resolution value (P2) into a JS promise
397     *     - and since P2 is still PENDING, we must add a listener to it in order to notify JS of its resolution later on
398     *     - this triggers PandaEtsVM::AddPromiseListener, which acquires already acquired promise_listeners_lock_ within
399     *       the same thread
400     *     - BOOM! Assertion fires.
401     */
402    return makeResolvedPromise("Panda");
403}
404
405async function testAsyncBoolean(): Promise<boolean> {
406    return true;
407}
408
409async function testAsyncByte(): Promise<byte> {
410    let x: byte = 127;
411    return x;
412}
413
414async function testAsyncChar(): Promise<char> {
415    return c'x';
416}
417
418async function testAsyncShort(): Promise<short> {
419    let x: short = 32767;
420    return x;
421}
422
423async function testAsyncInt(): Promise<int> {
424    return 5;
425}
426
427async function testAsyncLong(): Promise<long> {
428    return Long.MAX_VALUE;
429}
430
431async function testAsyncFloat(): Promise<float> {
432    let x: float = 3.14;
433    return x;
434}
435
436async function testAsyncDouble(): Promise<double> {
437    return 3.2;
438}
439
440async function testAsyncString(): Promise<String> {
441    return "Panda";
442}
443
444async function testAsyncVoid(): Promise<void> { return undefined }
445async function testAsyncVoidEmpty(): Promise<void> {}
446async function testAsyncVoidNothing() {}
447
448function testPromiseAllEmpty(): void {
449    globalTest = new Test();
450    let promises: Promise<Object>[] = [];
451    Promise.all(promises).then<void>((values: Array<Object>): void => {
452        if (values == null || values.length != 0) {
453            globalTest!.fail();
454        } else {
455            globalTest!.success();
456        }
457    });
458}
459
460function testPromiseAllResolved(): void {
461    globalTest = new Test(1);
462    let p1: Promise<Object> = Promise.resolve<Object>("abc");
463    let p2: Promise<Object> = Promise.resolve<Object>("def");
464    let p3: Promise<Object> = Promise.resolve<Object>("xyz");
465
466    Promise.all<Object>([
467        p1, p2, p3
468    ]).then<void>((values: Array<Object>): void => {
469        if (values.length != 3) {
470            globalTest!.fail();
471        }
472        if (values[0] != "abc") {
473            globalTest!.fail();
474        }
475        if (values[1] != "def") {
476            globalTest!.fail();
477        }
478        if (values[2] != "xyz") {
479            globalTest!.fail();
480        }
481        globalTest!.success();
482    });
483}
484
485function testPromiseAllRejected(): void {
486    globalTest = new Test(1);
487    let p1: Promise<Object> = Promise.resolve<Object>("abc");
488    let p2: Promise<Object> = Promise.reject<Object>("def");
489    let p3: Promise<Object> = Promise.resolve<Object>("xyz");
490    Promise.all([
491        p1, p2, p3
492    ]).then<void, void>((v: Object): void => {
493        globalTest!.fail();
494    }, (err: NullishType): void => {
495        if (err != "def") {
496            globalTest!.fail();
497        } else {
498            globalTest!.success();
499        }
500    });
501}
502
503function testPromiseAllRawValues(): void {
504    globalTest = new Test(1);
505    let p1: Object = "abc";
506    let p2: Object = "def";
507    let p3: Object = "xyz";
508
509    Promise.all<Object>([
510        p1, p2, p3
511    ]).then<void>((values: Array<Object>): void => {
512        if (values.length != 3) {
513            globalTest!.fail();
514        }
515        if (values[0] != "abc") {
516            globalTest!.fail();
517        }
518        if (values[1] != "def") {
519            globalTest!.fail();
520        }
521        if (values[2] != "xyz") {
522            globalTest!.fail();
523        }
524        globalTest!.success();
525    });
526}
527
528function testPromiseAllIterable(): void {
529    globalTest = new Test(1);
530    let array = new Array<Object|PromiseLike<Object>>();
531    array.push(Promise.resolve<Object>("abc"));
532    array.push("def");
533    array.push(Promise.resolve<Object>("xyz"));
534
535    Promise.all<Object>(array).then<void>((values: Array<Object>): void => {
536        if (values.length != 3) {
537            globalTest!.fail();
538        }
539        if (values[0] != "abc") {
540            globalTest!.fail();
541        }
542        if (values[1] != "def") {
543            globalTest!.fail();
544        }
545        if (values[2] != "xyz") {
546            globalTest!.fail();
547        }
548        globalTest!.success();
549    });
550}
551
552function testPromiseAllSettledEmpty(): void {
553    globalTest = new Test();
554    let promises: Promise<Object>[] = [];
555    Promise.allSettled<Object>(promises).then<void, void>((values: PromiseSettledResult<Object>[]): void => {
556        if (values.length != 0) {
557            globalTest!.fail();
558        }
559        globalTest!.success();
560    }, (err: NullishType): void => {
561        globalTest!.fail();
562    });
563}
564
565function testPromiseAllSettled(): void {
566    globalTest = new Test(1);
567    let p1: Promise<Object> = Promise.resolve<Object>("abc");
568    let p2: Promise<Object> = Promise.reject<Object>("def");
569    let p3: Promise<Object> = Promise.resolve<Object>("xyz");
570    Promise.allSettled([
571        p1, p2, p3
572    ]).then<void, void>((result: PromiseSettledResult<Object>[]): void => {
573        if (result.length != 3) {
574            globalTest!.fail();
575        }
576        if (!(result[0] instanceof PromiseFulfilledResult)) {
577            globalTest!.fail();
578        }
579        let res0 = result[0] as PromiseFulfilledResult<Object>;
580        if (res0.status != "fulfilled" || res0.value != "abc") {
581            globalTest!.fail();
582        }
583        if (!(result[1] instanceof PromiseRejectedResult)) {
584            globalTest!.fail();
585        }
586        let res1 = result[1] as PromiseRejectedResult;
587        if (res1.status != "rejected" || res1.reason != "def") {
588            globalTest!.fail();
589        }
590        if (!(result[2] instanceof PromiseFulfilledResult)) {
591            globalTest!.fail();
592        }
593        let res2 = result[2] as PromiseFulfilledResult<Object>;
594        if (res2.status != "fulfilled" || res2.value != "xyz") {
595            globalTest!.fail();
596        }
597        globalTest!.success();
598    }, (err: NullishType): void => {
599        globalTest!.fail();
600    });
601}
602
603function testPromiseAnyEmpty(): void {
604    globalTest = new Test();
605    let promises: Promise<Object>[] = [];
606    Promise.any(promises).then<void, void>((v: Object): void => {
607        globalTest!.fail();
608    }, (err: NullishType): void => {
609        if (err != null && err instanceof AggregateError) {
610            globalTest!.success();
611        } else {
612            globalTest!.fail();
613        }
614    });
615}
616
617function testPromiseAnyResolved(): void {
618    globalTest = new Test(1);
619    let p1: Promise<Object> = Promise.reject<Object>("abc");
620    let p2: Promise<Object> = Promise.reject<Object>("def");
621    let p3: Promise<Object> = Promise.resolve<Object>("xyz");
622    Promise.any([
623        p1, p2, p3
624    ]).then<void>((value: Object): void => {
625        if (value != "xyz") {
626            globalTest!.fail();
627        }
628        globalTest!.success();
629    });
630}
631
632function testPromiseAnyRejected(): void {
633    globalTest = new Test(1);
634    let p1: Promise<Object> = Promise.reject<Object>("abc");
635    let p2: Promise<Object> = Promise.reject<Object>("def");
636    let p3: Promise<Object> = Promise.reject<Object>("xyz");
637    Promise.any([
638        p1, p2, p3
639    ]).then<void, void>((v: Object): void => {
640        globalTest!.fail();
641    }, (err: NullishType): void => {
642        if (err == null || !(err instanceof AggregateError)) {
643            globalTest!.fail();
644        } else {
645            globalTest!.success();
646        }
647    });
648}
649
650function testPromiseAnyRawValues(): void {
651    globalTest = new Test(1);
652    Promise.any([
653        "abc", "def", "xyz"
654    ]).then<void>((value: Object): void => {
655        if (value != "abc") {
656            globalTest!.fail();
657        }
658        globalTest!.success();
659    });
660}
661
662function testPromiseAnyIterable(): void {
663    globalTest = new Test();
664    let array = new Array<Object|PromiseLike<Object>>();
665    array.push(Promise.reject<Object>("def"));
666    array.push(Promise.resolve<Object>("xyz"));
667    Promise.any<Object>(array).then<void>((value: Object): void => {
668        if (value != "xyz") {
669            globalTest!.fail();
670        }
671        globalTest!.success();
672    });
673}
674
675function testPromiseRaceResolved(): void {
676    globalTest = new Test(1);
677    let p1: Promise<Object> = Promise.resolve<Object>("abc");
678    let p2: Promise<Object> = Promise.reject<Object>("def");
679    Promise.race([
680        p1, p2
681    ]).then<void, void>((value: Object): void => {
682        if (value != "abc") {
683            globalTest!.fail();
684        }
685        globalTest!.success();
686    }, (error: NullishType): void => {
687        globalTest!.fail();
688    });
689}
690
691function testPromiseRaceRejected(): void {
692    globalTest = new Test(1);
693    let p1: Promise<Object> = Promise.reject<Object>("abc");
694    let p2: Promise<Object> = Promise.resolve<Object>("def");
695    Promise.race([
696        p1, p2
697    ]).then<void, void>((value: Object): void => {
698        globalTest!.fail();
699    }, (error: NullishType): void => {
700        if (error != "abc") {
701            globalTest!.fail();
702        }
703        globalTest!.success();
704    });
705}
706
707let promiseFixture: Promise<void>|null = null;
708
709function getPromise(): Promise<void> {
710    promiseFixture = Promise.resolve();
711    return promiseFixture!;
712}
713
714function setAndCheckPromise(p: Promise<void>): void {
715    globalTest = new Test();
716    if (promiseFixture == null) {
717        console.log("Promise is not set");
718        globalTest!.fail();
719    }
720    if (promiseFixture !== p) {
721        console.log("Expected the returned promise and the argument are the same but they differs");
722        globalTest!.fail();
723    }
724}
725
726function getTheSamePromise(p: Promise<void>): Promise<void> {
727    return p;
728}
729