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