11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ciconst common = require('../common');
31cb0ef41Sopenharmony_ciconst Countdown = require('../common/countdown');
41cb0ef41Sopenharmony_ciconst assert = require('assert');
51cb0ef41Sopenharmony_ciconst { AsyncLocalStorage } = require('async_hooks');
61cb0ef41Sopenharmony_ciconst http = require('http');
71cb0ef41Sopenharmony_ciconst cls = new AsyncLocalStorage();
81cb0ef41Sopenharmony_ciconst NUM_CLIENTS = 10;
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// Run multiple clients that receive data from a server
111cb0ef41Sopenharmony_ci// in multiple chunks, in a single non-closure function.
121cb0ef41Sopenharmony_ci// Use the AsyncLocalStorage (ALS) APIs to maintain the context
131cb0ef41Sopenharmony_ci// and data download. Make sure that individual clients
141cb0ef41Sopenharmony_ci// receive their respective data, with no conflicts.
151cb0ef41Sopenharmony_ci
161cb0ef41Sopenharmony_ci// Set up a server that sends large buffers of data, filled
171cb0ef41Sopenharmony_ci// with cardinal numbers, increasing per request
181cb0ef41Sopenharmony_cilet index = 0;
191cb0ef41Sopenharmony_ciconst server = http.createServer((q, r) => {
201cb0ef41Sopenharmony_ci  // Send a large chunk as response, otherwise the data
211cb0ef41Sopenharmony_ci  // may be sent in a single chunk, and the callback in the
221cb0ef41Sopenharmony_ci  // client may be called only once, defeating the purpose of test
231cb0ef41Sopenharmony_ci  r.end((index++ % 10).toString().repeat(1024 * 1024));
241cb0ef41Sopenharmony_ci});
251cb0ef41Sopenharmony_ci
261cb0ef41Sopenharmony_ciconst countdown = new Countdown(NUM_CLIENTS, () => {
271cb0ef41Sopenharmony_ci  server.close();
281cb0ef41Sopenharmony_ci});
291cb0ef41Sopenharmony_ci
301cb0ef41Sopenharmony_ciserver.listen(0, common.mustCall(() => {
311cb0ef41Sopenharmony_ci  for (let i = 0; i < NUM_CLIENTS; i++) {
321cb0ef41Sopenharmony_ci    cls.run(new Map(), common.mustCall(() => {
331cb0ef41Sopenharmony_ci      const options = { port: server.address().port };
341cb0ef41Sopenharmony_ci      const req = http.get(options, common.mustCall((res) => {
351cb0ef41Sopenharmony_ci        const store = cls.getStore();
361cb0ef41Sopenharmony_ci        store.set('data', '');
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci        // Make ondata and onend non-closure
391cb0ef41Sopenharmony_ci        // functions and fully dependent on ALS
401cb0ef41Sopenharmony_ci        res.setEncoding('utf8');
411cb0ef41Sopenharmony_ci        res.on('data', ondata);
421cb0ef41Sopenharmony_ci        res.on('end', common.mustCall(onend));
431cb0ef41Sopenharmony_ci      }));
441cb0ef41Sopenharmony_ci      req.end();
451cb0ef41Sopenharmony_ci    }));
461cb0ef41Sopenharmony_ci  }
471cb0ef41Sopenharmony_ci}));
481cb0ef41Sopenharmony_ci
491cb0ef41Sopenharmony_ci// Accumulate the current data chunk with the store data
501cb0ef41Sopenharmony_cifunction ondata(d) {
511cb0ef41Sopenharmony_ci  const store = cls.getStore();
521cb0ef41Sopenharmony_ci  assert.notStrictEqual(store, undefined);
531cb0ef41Sopenharmony_ci  let chunk = store.get('data');
541cb0ef41Sopenharmony_ci  chunk += d;
551cb0ef41Sopenharmony_ci  store.set('data', chunk);
561cb0ef41Sopenharmony_ci}
571cb0ef41Sopenharmony_ci
581cb0ef41Sopenharmony_ci// Retrieve the store data, and test for homogeneity
591cb0ef41Sopenharmony_cifunction onend() {
601cb0ef41Sopenharmony_ci  const store = cls.getStore();
611cb0ef41Sopenharmony_ci  assert.notStrictEqual(store, undefined);
621cb0ef41Sopenharmony_ci  const data = store.get('data');
631cb0ef41Sopenharmony_ci  assert.strictEqual(data, data[0].repeat(data.length));
641cb0ef41Sopenharmony_ci  countdown.dec();
651cb0ef41Sopenharmony_ci}
66