11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst {
41cb0ef41Sopenharmony_ci  mustCall,
51cb0ef41Sopenharmony_ci  mustNotCall,
61cb0ef41Sopenharmony_ci  hasCrypto,
71cb0ef41Sopenharmony_ci  platformTimeout,
81cb0ef41Sopenharmony_ci  skip
91cb0ef41Sopenharmony_ci} = require('../common');
101cb0ef41Sopenharmony_ciif (!hasCrypto)
111cb0ef41Sopenharmony_ci  skip('missing crypto');
121cb0ef41Sopenharmony_ciconst { strictEqual } = require('assert');
131cb0ef41Sopenharmony_ciconst {
141cb0ef41Sopenharmony_ci  createServer,
151cb0ef41Sopenharmony_ci  connect,
161cb0ef41Sopenharmony_ci  constants: {
171cb0ef41Sopenharmony_ci    HTTP2_HEADER_STATUS,
181cb0ef41Sopenharmony_ci    HTTP_STATUS_OK
191cb0ef41Sopenharmony_ci  }
201cb0ef41Sopenharmony_ci} = require('http2');
211cb0ef41Sopenharmony_ci
221cb0ef41Sopenharmony_ci{
231cb0ef41Sopenharmony_ci  // Http2ServerResponse.end accepts chunk, encoding, cb as args
241cb0ef41Sopenharmony_ci  // It may be invoked repeatedly without throwing errors
251cb0ef41Sopenharmony_ci  // but callback will only be called once
261cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
271cb0ef41Sopenharmony_ci    response.end('end', 'utf8', mustCall(() => {
281cb0ef41Sopenharmony_ci      response.end(mustCall());
291cb0ef41Sopenharmony_ci      process.nextTick(() => {
301cb0ef41Sopenharmony_ci        response.end(mustCall());
311cb0ef41Sopenharmony_ci        server.close();
321cb0ef41Sopenharmony_ci      });
331cb0ef41Sopenharmony_ci    }));
341cb0ef41Sopenharmony_ci    response.on('finish', mustCall(() => {
351cb0ef41Sopenharmony_ci      response.end(mustCall());
361cb0ef41Sopenharmony_ci    }));
371cb0ef41Sopenharmony_ci    response.end(mustCall());
381cb0ef41Sopenharmony_ci  }));
391cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
401cb0ef41Sopenharmony_ci    let data = '';
411cb0ef41Sopenharmony_ci    const { port } = server.address();
421cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
431cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
441cb0ef41Sopenharmony_ci      const headers = {
451cb0ef41Sopenharmony_ci        ':path': '/',
461cb0ef41Sopenharmony_ci        ':method': 'GET',
471cb0ef41Sopenharmony_ci        ':scheme': 'http',
481cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
491cb0ef41Sopenharmony_ci      };
501cb0ef41Sopenharmony_ci      const request = client.request(headers);
511cb0ef41Sopenharmony_ci      request.setEncoding('utf8');
521cb0ef41Sopenharmony_ci      request.on('data', (chunk) => (data += chunk));
531cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
541cb0ef41Sopenharmony_ci        strictEqual(data, 'end');
551cb0ef41Sopenharmony_ci        client.close();
561cb0ef41Sopenharmony_ci      }));
571cb0ef41Sopenharmony_ci      request.end();
581cb0ef41Sopenharmony_ci      request.resume();
591cb0ef41Sopenharmony_ci    }));
601cb0ef41Sopenharmony_ci  }));
611cb0ef41Sopenharmony_ci}
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci{
641cb0ef41Sopenharmony_ci  // Http2ServerResponse.end should return self after end
651cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
661cb0ef41Sopenharmony_ci    strictEqual(response, response.end());
671cb0ef41Sopenharmony_ci    strictEqual(response, response.end());
681cb0ef41Sopenharmony_ci    server.close();
691cb0ef41Sopenharmony_ci  }));
701cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
711cb0ef41Sopenharmony_ci    const { port } = server.address();
721cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
731cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
741cb0ef41Sopenharmony_ci      const headers = {
751cb0ef41Sopenharmony_ci        ':path': '/',
761cb0ef41Sopenharmony_ci        ':method': 'GET',
771cb0ef41Sopenharmony_ci        ':scheme': 'http',
781cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
791cb0ef41Sopenharmony_ci      };
801cb0ef41Sopenharmony_ci      const request = client.request(headers);
811cb0ef41Sopenharmony_ci      request.setEncoding('utf8');
821cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
831cb0ef41Sopenharmony_ci        client.close();
841cb0ef41Sopenharmony_ci      }));
851cb0ef41Sopenharmony_ci      request.end();
861cb0ef41Sopenharmony_ci      request.resume();
871cb0ef41Sopenharmony_ci    }));
881cb0ef41Sopenharmony_ci  }));
891cb0ef41Sopenharmony_ci}
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci{
921cb0ef41Sopenharmony_ci  // Http2ServerResponse.end can omit encoding arg, sets it to utf-8
931cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
941cb0ef41Sopenharmony_ci    response.end('test\uD83D\uDE00', mustCall(() => {
951cb0ef41Sopenharmony_ci      server.close();
961cb0ef41Sopenharmony_ci    }));
971cb0ef41Sopenharmony_ci  }));
981cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
991cb0ef41Sopenharmony_ci    let data = '';
1001cb0ef41Sopenharmony_ci    const { port } = server.address();
1011cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
1021cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
1031cb0ef41Sopenharmony_ci      const headers = {
1041cb0ef41Sopenharmony_ci        ':path': '/',
1051cb0ef41Sopenharmony_ci        ':method': 'GET',
1061cb0ef41Sopenharmony_ci        ':scheme': 'http',
1071cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
1081cb0ef41Sopenharmony_ci      };
1091cb0ef41Sopenharmony_ci      const request = client.request(headers);
1101cb0ef41Sopenharmony_ci      request.setEncoding('utf8');
1111cb0ef41Sopenharmony_ci      request.on('data', (chunk) => (data += chunk));
1121cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
1131cb0ef41Sopenharmony_ci        strictEqual(data, 'test\uD83D\uDE00');
1141cb0ef41Sopenharmony_ci        client.close();
1151cb0ef41Sopenharmony_ci      }));
1161cb0ef41Sopenharmony_ci      request.end();
1171cb0ef41Sopenharmony_ci      request.resume();
1181cb0ef41Sopenharmony_ci    }));
1191cb0ef41Sopenharmony_ci  }));
1201cb0ef41Sopenharmony_ci}
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci{
1231cb0ef41Sopenharmony_ci  // Http2ServerResponse.end can omit chunk & encoding args
1241cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
1251cb0ef41Sopenharmony_ci    response.end(mustCall(() => {
1261cb0ef41Sopenharmony_ci      server.close();
1271cb0ef41Sopenharmony_ci    }));
1281cb0ef41Sopenharmony_ci  }));
1291cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
1301cb0ef41Sopenharmony_ci    const { port } = server.address();
1311cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
1321cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
1331cb0ef41Sopenharmony_ci      const headers = {
1341cb0ef41Sopenharmony_ci        ':path': '/',
1351cb0ef41Sopenharmony_ci        ':method': 'GET',
1361cb0ef41Sopenharmony_ci        ':scheme': 'http',
1371cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
1381cb0ef41Sopenharmony_ci      };
1391cb0ef41Sopenharmony_ci      const request = client.request(headers);
1401cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
1411cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => client.close()));
1421cb0ef41Sopenharmony_ci      request.end();
1431cb0ef41Sopenharmony_ci      request.resume();
1441cb0ef41Sopenharmony_ci    }));
1451cb0ef41Sopenharmony_ci  }));
1461cb0ef41Sopenharmony_ci}
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci{
1491cb0ef41Sopenharmony_ci  // Http2ServerResponse.end is necessary on HEAD requests in compat
1501cb0ef41Sopenharmony_ci  // for http1 compatibility
1511cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
1521cb0ef41Sopenharmony_ci    strictEqual(response.writableEnded, false);
1531cb0ef41Sopenharmony_ci    strictEqual(response.finished, false);
1541cb0ef41Sopenharmony_ci    response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
1551cb0ef41Sopenharmony_ci    strictEqual(response.finished, false);
1561cb0ef41Sopenharmony_ci    response.end('data', mustCall());
1571cb0ef41Sopenharmony_ci    strictEqual(response.writableEnded, true);
1581cb0ef41Sopenharmony_ci    strictEqual(response.finished, true);
1591cb0ef41Sopenharmony_ci  }));
1601cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
1611cb0ef41Sopenharmony_ci    const { port } = server.address();
1621cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
1631cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
1641cb0ef41Sopenharmony_ci      const headers = {
1651cb0ef41Sopenharmony_ci        ':path': '/',
1661cb0ef41Sopenharmony_ci        ':method': 'HEAD',
1671cb0ef41Sopenharmony_ci        ':scheme': 'http',
1681cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
1691cb0ef41Sopenharmony_ci      };
1701cb0ef41Sopenharmony_ci      const request = client.request(headers);
1711cb0ef41Sopenharmony_ci      request.on('response', mustCall((headers, flags) => {
1721cb0ef41Sopenharmony_ci        strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
1731cb0ef41Sopenharmony_ci        strictEqual(flags, 5); // The end of stream flag is set
1741cb0ef41Sopenharmony_ci        strictEqual(headers.foo, 'bar');
1751cb0ef41Sopenharmony_ci      }));
1761cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
1771cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
1781cb0ef41Sopenharmony_ci        client.close();
1791cb0ef41Sopenharmony_ci        server.close();
1801cb0ef41Sopenharmony_ci      }));
1811cb0ef41Sopenharmony_ci      request.end();
1821cb0ef41Sopenharmony_ci      request.resume();
1831cb0ef41Sopenharmony_ci    }));
1841cb0ef41Sopenharmony_ci  }));
1851cb0ef41Sopenharmony_ci}
1861cb0ef41Sopenharmony_ci
1871cb0ef41Sopenharmony_ci{
1881cb0ef41Sopenharmony_ci  // .end should trigger 'end' event on request if user did not attempt
1891cb0ef41Sopenharmony_ci  // to read from the request
1901cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
1911cb0ef41Sopenharmony_ci    request.on('end', mustCall());
1921cb0ef41Sopenharmony_ci    response.end();
1931cb0ef41Sopenharmony_ci  }));
1941cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
1951cb0ef41Sopenharmony_ci    const { port } = server.address();
1961cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
1971cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
1981cb0ef41Sopenharmony_ci      const headers = {
1991cb0ef41Sopenharmony_ci        ':path': '/',
2001cb0ef41Sopenharmony_ci        ':method': 'HEAD',
2011cb0ef41Sopenharmony_ci        ':scheme': 'http',
2021cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
2031cb0ef41Sopenharmony_ci      };
2041cb0ef41Sopenharmony_ci      const request = client.request(headers);
2051cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
2061cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
2071cb0ef41Sopenharmony_ci        client.close();
2081cb0ef41Sopenharmony_ci        server.close();
2091cb0ef41Sopenharmony_ci      }));
2101cb0ef41Sopenharmony_ci      request.end();
2111cb0ef41Sopenharmony_ci      request.resume();
2121cb0ef41Sopenharmony_ci    }));
2131cb0ef41Sopenharmony_ci  }));
2141cb0ef41Sopenharmony_ci}
2151cb0ef41Sopenharmony_ci
2161cb0ef41Sopenharmony_ci
2171cb0ef41Sopenharmony_ci{
2181cb0ef41Sopenharmony_ci  // Should be able to call .end with cb from stream 'close'
2191cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
2201cb0ef41Sopenharmony_ci    response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
2211cb0ef41Sopenharmony_ci    response.stream.on('close', mustCall(() => {
2221cb0ef41Sopenharmony_ci      response.end(mustCall());
2231cb0ef41Sopenharmony_ci    }));
2241cb0ef41Sopenharmony_ci  }));
2251cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
2261cb0ef41Sopenharmony_ci    const { port } = server.address();
2271cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
2281cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
2291cb0ef41Sopenharmony_ci      const headers = {
2301cb0ef41Sopenharmony_ci        ':path': '/',
2311cb0ef41Sopenharmony_ci        ':method': 'HEAD',
2321cb0ef41Sopenharmony_ci        ':scheme': 'http',
2331cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
2341cb0ef41Sopenharmony_ci      };
2351cb0ef41Sopenharmony_ci      const request = client.request(headers);
2361cb0ef41Sopenharmony_ci      request.on('response', mustCall((headers, flags) => {
2371cb0ef41Sopenharmony_ci        strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
2381cb0ef41Sopenharmony_ci        strictEqual(flags, 5); // The end of stream flag is set
2391cb0ef41Sopenharmony_ci        strictEqual(headers.foo, 'bar');
2401cb0ef41Sopenharmony_ci      }));
2411cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
2421cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
2431cb0ef41Sopenharmony_ci        client.close();
2441cb0ef41Sopenharmony_ci        server.close();
2451cb0ef41Sopenharmony_ci      }));
2461cb0ef41Sopenharmony_ci      request.end();
2471cb0ef41Sopenharmony_ci      request.resume();
2481cb0ef41Sopenharmony_ci    }));
2491cb0ef41Sopenharmony_ci  }));
2501cb0ef41Sopenharmony_ci}
2511cb0ef41Sopenharmony_ci
2521cb0ef41Sopenharmony_ci{
2531cb0ef41Sopenharmony_ci  // Should be able to respond to HEAD request after timeout
2541cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
2551cb0ef41Sopenharmony_ci    setTimeout(mustCall(() => {
2561cb0ef41Sopenharmony_ci      response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
2571cb0ef41Sopenharmony_ci      response.end('data', mustCall());
2581cb0ef41Sopenharmony_ci    }), platformTimeout(10));
2591cb0ef41Sopenharmony_ci  }));
2601cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
2611cb0ef41Sopenharmony_ci    const { port } = server.address();
2621cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
2631cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
2641cb0ef41Sopenharmony_ci      const headers = {
2651cb0ef41Sopenharmony_ci        ':path': '/',
2661cb0ef41Sopenharmony_ci        ':method': 'HEAD',
2671cb0ef41Sopenharmony_ci        ':scheme': 'http',
2681cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
2691cb0ef41Sopenharmony_ci      };
2701cb0ef41Sopenharmony_ci      const request = client.request(headers);
2711cb0ef41Sopenharmony_ci      request.on('response', mustCall((headers, flags) => {
2721cb0ef41Sopenharmony_ci        strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
2731cb0ef41Sopenharmony_ci        strictEqual(flags, 5); // The end of stream flag is set
2741cb0ef41Sopenharmony_ci        strictEqual(headers.foo, 'bar');
2751cb0ef41Sopenharmony_ci      }));
2761cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
2771cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
2781cb0ef41Sopenharmony_ci        client.close();
2791cb0ef41Sopenharmony_ci        server.close();
2801cb0ef41Sopenharmony_ci      }));
2811cb0ef41Sopenharmony_ci      request.end();
2821cb0ef41Sopenharmony_ci      request.resume();
2831cb0ef41Sopenharmony_ci    }));
2841cb0ef41Sopenharmony_ci  }));
2851cb0ef41Sopenharmony_ci}
2861cb0ef41Sopenharmony_ci
2871cb0ef41Sopenharmony_ci{
2881cb0ef41Sopenharmony_ci  // Finish should only trigger after 'end' is called
2891cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
2901cb0ef41Sopenharmony_ci    let finished = false;
2911cb0ef41Sopenharmony_ci    response.writeHead(HTTP_STATUS_OK, { foo: 'bar' });
2921cb0ef41Sopenharmony_ci    response.on('finish', mustCall(() => {
2931cb0ef41Sopenharmony_ci      finished = false;
2941cb0ef41Sopenharmony_ci    }));
2951cb0ef41Sopenharmony_ci    response.end('data', mustCall(() => {
2961cb0ef41Sopenharmony_ci      strictEqual(finished, false);
2971cb0ef41Sopenharmony_ci      response.end('data', mustCall());
2981cb0ef41Sopenharmony_ci    }));
2991cb0ef41Sopenharmony_ci  }));
3001cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
3011cb0ef41Sopenharmony_ci    const { port } = server.address();
3021cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
3031cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
3041cb0ef41Sopenharmony_ci      const headers = {
3051cb0ef41Sopenharmony_ci        ':path': '/',
3061cb0ef41Sopenharmony_ci        ':method': 'HEAD',
3071cb0ef41Sopenharmony_ci        ':scheme': 'http',
3081cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
3091cb0ef41Sopenharmony_ci      };
3101cb0ef41Sopenharmony_ci      const request = client.request(headers);
3111cb0ef41Sopenharmony_ci      request.on('response', mustCall((headers, flags) => {
3121cb0ef41Sopenharmony_ci        strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
3131cb0ef41Sopenharmony_ci        strictEqual(flags, 5); // The end of stream flag is set
3141cb0ef41Sopenharmony_ci        strictEqual(headers.foo, 'bar');
3151cb0ef41Sopenharmony_ci      }));
3161cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
3171cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
3181cb0ef41Sopenharmony_ci        client.close();
3191cb0ef41Sopenharmony_ci        server.close();
3201cb0ef41Sopenharmony_ci      }));
3211cb0ef41Sopenharmony_ci      request.end();
3221cb0ef41Sopenharmony_ci      request.resume();
3231cb0ef41Sopenharmony_ci    }));
3241cb0ef41Sopenharmony_ci  }));
3251cb0ef41Sopenharmony_ci}
3261cb0ef41Sopenharmony_ci
3271cb0ef41Sopenharmony_ci{
3281cb0ef41Sopenharmony_ci  // Should be able to respond to HEAD with just .end
3291cb0ef41Sopenharmony_ci  const server = createServer(mustCall((request, response) => {
3301cb0ef41Sopenharmony_ci    response.end('data', mustCall());
3311cb0ef41Sopenharmony_ci    response.end(mustCall());
3321cb0ef41Sopenharmony_ci  }));
3331cb0ef41Sopenharmony_ci  server.listen(0, mustCall(() => {
3341cb0ef41Sopenharmony_ci    const { port } = server.address();
3351cb0ef41Sopenharmony_ci    const url = `http://localhost:${port}`;
3361cb0ef41Sopenharmony_ci    const client = connect(url, mustCall(() => {
3371cb0ef41Sopenharmony_ci      const headers = {
3381cb0ef41Sopenharmony_ci        ':path': '/',
3391cb0ef41Sopenharmony_ci        ':method': 'HEAD',
3401cb0ef41Sopenharmony_ci        ':scheme': 'http',
3411cb0ef41Sopenharmony_ci        ':authority': `localhost:${port}`
3421cb0ef41Sopenharmony_ci      };
3431cb0ef41Sopenharmony_ci      const request = client.request(headers);
3441cb0ef41Sopenharmony_ci      request.on('response', mustCall((headers, flags) => {
3451cb0ef41Sopenharmony_ci        strictEqual(headers[HTTP2_HEADER_STATUS], HTTP_STATUS_OK);
3461cb0ef41Sopenharmony_ci        strictEqual(flags, 5); // The end of stream flag is set
3471cb0ef41Sopenharmony_ci      }));
3481cb0ef41Sopenharmony_ci      request.on('data', mustNotCall());
3491cb0ef41Sopenharmony_ci      request.on('end', mustCall(() => {
3501cb0ef41Sopenharmony_ci        client.close();
3511cb0ef41Sopenharmony_ci        server.close();
3521cb0ef41Sopenharmony_ci      }));
3531cb0ef41Sopenharmony_ci      request.end();
3541cb0ef41Sopenharmony_ci      request.resume();
3551cb0ef41Sopenharmony_ci    }));
3561cb0ef41Sopenharmony_ci  }));
3571cb0ef41Sopenharmony_ci}
358