11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ci
41cb0ef41Sopenharmony_ci// This test ensures async hooks are being properly called
51cb0ef41Sopenharmony_ci// when using async-await mechanics. This involves:
61cb0ef41Sopenharmony_ci// 1. Checking that all initialized promises are being resolved
71cb0ef41Sopenharmony_ci// 2. Checking that for each 'before' corresponding hook 'after' hook is called
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ciconst assert = require('assert');
101cb0ef41Sopenharmony_ciconst initHooks = require('./init-hooks');
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ciconst util = require('util');
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ciconst sleep = util.promisify(setTimeout);
151cb0ef41Sopenharmony_ci// Either 'inited' or 'resolved'
161cb0ef41Sopenharmony_ciconst promisesInitState = new Map();
171cb0ef41Sopenharmony_ci// Either 'before' or 'after' AND asyncId must be present in the other map
181cb0ef41Sopenharmony_ciconst promisesExecutionState = new Map();
191cb0ef41Sopenharmony_ci
201cb0ef41Sopenharmony_ciconst hooks = initHooks({
211cb0ef41Sopenharmony_ci  oninit,
221cb0ef41Sopenharmony_ci  onbefore,
231cb0ef41Sopenharmony_ci  onafter,
241cb0ef41Sopenharmony_ci  ondestroy: null,  // Intentionally not tested, since it will be removed soon
251cb0ef41Sopenharmony_ci  onpromiseResolve,
261cb0ef41Sopenharmony_ci});
271cb0ef41Sopenharmony_cihooks.enable();
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_cifunction oninit(asyncId, type) {
301cb0ef41Sopenharmony_ci  if (type === 'PROMISE') {
311cb0ef41Sopenharmony_ci    promisesInitState.set(asyncId, 'inited');
321cb0ef41Sopenharmony_ci  }
331cb0ef41Sopenharmony_ci}
341cb0ef41Sopenharmony_ci
351cb0ef41Sopenharmony_cifunction onbefore(asyncId) {
361cb0ef41Sopenharmony_ci  if (!promisesInitState.has(asyncId)) {
371cb0ef41Sopenharmony_ci    return;
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci  promisesExecutionState.set(asyncId, 'before');
401cb0ef41Sopenharmony_ci}
411cb0ef41Sopenharmony_ci
421cb0ef41Sopenharmony_cifunction onafter(asyncId) {
431cb0ef41Sopenharmony_ci  if (!promisesInitState.has(asyncId)) {
441cb0ef41Sopenharmony_ci    return;
451cb0ef41Sopenharmony_ci  }
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci  assert.strictEqual(promisesExecutionState.get(asyncId), 'before',
481cb0ef41Sopenharmony_ci                     'after hook called for promise without prior call' +
491cb0ef41Sopenharmony_ci                     'to before hook');
501cb0ef41Sopenharmony_ci  assert.strictEqual(promisesInitState.get(asyncId), 'resolved',
511cb0ef41Sopenharmony_ci                     'after hook called for promise without prior call' +
521cb0ef41Sopenharmony_ci                     'to resolve hook');
531cb0ef41Sopenharmony_ci  promisesExecutionState.set(asyncId, 'after');
541cb0ef41Sopenharmony_ci}
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_cifunction onpromiseResolve(asyncId) {
571cb0ef41Sopenharmony_ci  assert(promisesInitState.has(asyncId),
581cb0ef41Sopenharmony_ci         'resolve hook called for promise without prior call to init hook');
591cb0ef41Sopenharmony_ci
601cb0ef41Sopenharmony_ci  promisesInitState.set(asyncId, 'resolved');
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ciconst timeout = common.platformTimeout(10);
641cb0ef41Sopenharmony_ci
651cb0ef41Sopenharmony_cifunction checkPromisesInitState() {
661cb0ef41Sopenharmony_ci  for (const initState of promisesInitState.values()) {
671cb0ef41Sopenharmony_ci    // Promise should not be initialized without being resolved.
681cb0ef41Sopenharmony_ci    assert.strictEqual(initState, 'resolved');
691cb0ef41Sopenharmony_ci  }
701cb0ef41Sopenharmony_ci}
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_cifunction checkPromisesExecutionState() {
731cb0ef41Sopenharmony_ci  for (const executionState of promisesExecutionState.values()) {
741cb0ef41Sopenharmony_ci    // Check for mismatch between before and after hook calls.
751cb0ef41Sopenharmony_ci    assert.strictEqual(executionState, 'after');
761cb0ef41Sopenharmony_ci  }
771cb0ef41Sopenharmony_ci}
781cb0ef41Sopenharmony_ci
791cb0ef41Sopenharmony_ciprocess.on('beforeExit', common.mustCall(() => {
801cb0ef41Sopenharmony_ci  hooks.disable();
811cb0ef41Sopenharmony_ci  hooks.sanityCheck('PROMISE');
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  checkPromisesInitState();
841cb0ef41Sopenharmony_ci  checkPromisesExecutionState();
851cb0ef41Sopenharmony_ci}));
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ciasync function asyncFunc() {
881cb0ef41Sopenharmony_ci  await sleep(timeout);
891cb0ef41Sopenharmony_ci}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ciasyncFunc();
92