![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Я придумал решение для запуска REPL приложения, упомянутое в предыдущем посте. Напомню формулировку: есть интерактивная процедура на Си++ со следующим интерфейсом.
Процедура работает в стиле REPL: берет ввод из входного потока, обрабатывает, выдаёт результат в выходной поток и ждёт следующего ввода. Мы хотим запустить эту процедуру из нашей программы на Си++, посылать ей команды и получать результат. Это, в частности, полезно для автоматического тестирования. Примерно так:void application(std::istream &input, std::ostream &output);
Решение выглядит в виде класса Interact и работает следующим образом:send("foo\n");
std::string reply = receive();
REQUIRE(reply == "bar\n");
Исходники можно взять на Гитхабе: https://github.com/sergev/interactРеализация должна быть понятна из комментариев.#include "interact.h" Interact session(application);
REQUIRE(session.receive() == "Hello!\n");
session.send("foo\n");
REQUIRE(session.receive() == "bar\n");
no subject
Date: 2020-08-14 07:58 (UTC)В старом C++ его не было, а в других языках он обязателен.
Очень советую, помогает избежать ошибок из-за опечатки в имени метода или изменении типа аргумента.
no subject
Date: 2020-08-14 08:05 (UTC)no subject
Date: 2020-08-14 20:47 (UTC)А const функций здесь не имеется.
no subject
Date: 2020-08-14 15:31 (UTC)no subject
Date: 2020-08-14 17:16 (UTC)no subject
Date: 2020-08-14 18:49 (UTC)no subject
Date: 2020-08-14 19:03 (UTC)Посадка посредством fuzzing это будет прикольно!
no subject
Date: 2020-08-14 20:13 (UTC)no subject
Date: 2020-08-14 20:43 (UTC)А можешь отыскать такие же короткие решения для всех уровней, от 0 до 9?
Хотя для уровня 0 его нету, как я догадываюсь.
Мне нужен набор тестов с более-менее приличным покрытием, чтобы начать переписывать на Rust.
no subject
Date: 2020-08-15 01:44 (UTC)Это решение годится для большинства уровней (кроме 1 и 2, если не ошибаюсь).
no subject
Date: 2020-08-15 02:51 (UTC)no subject
Date: 2020-08-14 16:52 (UTC)Ну это странный дизайн. А если я еще раз receive() вызову? Или это FSM, и каждый send изменяет статус, а потом receive возвращает аутпут в этом статусе? Не очевидно. По идее, это должна быть функция: вход -> выход, без всякого там state.
no subject
Date: 2020-08-14 17:06 (UTC)no subject
Date: 2020-08-14 17:23 (UTC)Ну в варианте send/receive это уже не выглядело как repl.
Так у нас же функция, так? Ну и смотреть на это как на функцию.
no subject
Date: 2020-08-14 17:49 (UTC)no subject
Date: 2020-08-14 19:26 (UTC)Я в чисто научном смысле. Как происходит обмен, не столь важно. Важно, что есть вход, и есть выход, и нет никакого внутреннего состояния.
no subject
Date: 2020-08-14 20:07 (UTC)f1(x1)
f2(x1,x2)
f3(x1,x2,x3)
...
fN(x1,x2,...,xN)
Здесь x1 - первый ввод, x2 - второй ввод и так далее.
Результат после ввода xN зависит как от xN, так и от всех предыдущих вводов.
Функция на каждом шаге тоже разная.
no subject
Date: 2020-08-14 20:17 (UTC)О, т.е. есть State. Ну окей. Можно рисовать как (S,I) => (S,O)
no subject
Date: 2020-08-14 20:31 (UTC)x2 = g1(x1,f(x1))
x3 = g2(x1,x2,f1(x1),f2(x1,x2))
и так далее. Здесь g1(), g2() и т.д. есть реакция юзера на поведение процедуры.
То есть имеем два дискретных ряда функций со взаимной зависимостью.
no subject
Date: 2020-08-14 21:12 (UTC)Э не. Это тест будет генерировать в зависимости - если такой тест. Или такой юзер. Но для тестирования собственно функциональности такая гипотеза вредна.
no subject
Date: 2020-08-14 23:15 (UTC)Мы можем тестировать application, а можем тестировать сам тест.
Старая программистская шутка: тестирование есть процесс поиска ошибок в тестах.
no subject
Date: 2020-08-14 18:07 (UTC)no subject
Date: 2020-08-20 09:38 (UTC)> берет ввод из входного потока, обрабатывает, выдаёт результат в выходной поток и ждёт следующего ввода
Задумался о тупиках развития машинных языков. Второй вариант компилировался бы не хуже, а по понятности на 2..3 порядка лучше.