Как записать строковые данные в поток кусками, а не комом - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть скрипт node.js, который должен принимать данные utf8 на STDIN и выводить другие данные utf8 на STDOUT. Он предназначен для приема строки (ий) TAP от обработчика инфраструктуры тестирования ленты через канал оболочки и небольшого изменения:

#!/usr/bin/env node
'use strict';

process.stdin.setDefaultEncoding('utf8');
process.stdout.setDefaultEncoding('utf8');
process.stdin.on('readable', () => {
  let chunk;
  while ((chunk = process.stdin.read()) !== null) {
    process.stdout.write('chunk: ' + chunk);
  }
});

process.stdin.on('end', () => {
  process.stdout.write('end\n');
});

Когда я запускаю тест с ленточным тестом npm run test-unit test/unit/main.test.js | ./format.js, я получаю (далее я буду называть его " live output "):

chunk: 
> dummy@0.0.0 test-unit /path/dummy/zzz
> tape "test/unit/main.test.js"

chunk: TAP version 13
chunk: # test 1
chunk: # comment 1
chunk: ok 1 should be equal
chunk: 
1..1
chunk: # tests 1
# pass  1

# ok
chunk: 
end

Итак, вы можете видеть, что данные, вроде как, были записаны 8 раз по 8 кусочкам.

У меня вопрос, как я могу смоделировать это поведение в тесте?

В тесте я породил другой процесс с spawn('./format.js'), но как я могу записать в этот процесс 'STDIN, чтобы считывать те же данные 8 раз, как из репортера крана.

Я разделил исходный вывод касания (без меток «чанков») на массив строк (эквивалентный чанкам из живого вывода ) и попытался записать каждую строку в отдельном вызове записи вЗатем spawned.stdin протестирует вывод format.js:

let spawned = spawn('./format.js');
let chunksOriginal = [
  // chunks here
];


spawned.stdout.on('readable', () => {
  console.log(spawned.stdout.read());
});
chunksOriginal.forEach((chunk, i) => {
  spawned.stdin.write(chunk);
});

Я ожидалconsole.log извергать ту же строку, что и live output , или, по крайней мере, быть только первым фрагментом из него, но я получил:

chunk: 
> dummy@0.0.0 test-unit /path/dummy/zzz
> tape "test/unit/main.test.js"

TAP version 13
# test 1
# comment 1
ok 1 should be equal

1..1
# tests 1
# pass  1

# ok

end

Как видите, данные быличитать format.js только один раз, с отметкой выше.Я пытался выдать «читаемое» событие в цикле forEach перед вызовом записи, это тоже не помогло:

chunksOriginal.forEach((chunk, i) => {
  spawned.stdin.emit('readable');
  spawned.stdin.write(chunk);
});

Я подозреваю, что проблема в том, что я не понимаю концептуальноIPC в node.js и bash.Данные в «живом выводе», вероятно, записываются через так называемый буфер node.js.

Я не прошу точного решения проблемы, хотя я 'Буду очень признателен, если кто-то предоставит это.

Просто подсказка на концептуальном уровне, где я должен искать, в каких документах, чтобы решить эту проблему, будет оценена

1 Ответ

0 голосов
/ 24 сентября 2019

Также я попытался использовать setTimeout, чтобы сделать процесс записи асинхронным, хотя я забыл упомянуть об этом в вопросе, но это тоже не помогло:

chunksOriginal.forEach((chunk, i) => {
  setTimeout(() => {
    spawned.stdin.emit('readable');
    spawned.stdin.write(chunk);
  }, i);
});

Затем я дал ему еще одну попытку и увеличил задержку i * 100 мс, а именно, и это сработало:

chunksOriginal.forEach((chunk, i) => {
  setTimeout(() => {
    spawned.stdin.write(chunk);
  }, i * 100);
});

Это помогло, теперь format.js получает то же количество чанков от фиктивного ввода, что ион получает от живого (хотя все это может потребовать некоторой настройки, создания конфигурации).

Также стоит отметить, что вызов emit не нужен .

...