
Взаимодействие Web-сервера и сервера тестирования
Как Web-сервер, так и сервер тестирования написаны на языке Go и для обмена сообщениями используют сетевые именованные типизированные каналы, реализованные в пакете netchan стандартной библиотеки языка Go. При этом Web-сервер поддерживает работу сразу с несколькими серверами тестирования, что предоставляет возможность разворачивания системы тестирования T-BMSTU на кластерной вычислительной системе.
Сервер тестирования сам инициирует соединение с Web-сервером. Для этого он устанавливает соединение с каналом «setup», экспортируемым Web-сервером. Канал «setup» направлен от Web-сервера к серверу тестирования. Из него сервер тестирования считывает пакет Setup, структура которого описана в таблице 1. В этом пакете записаны сгенерированные Web-сервером уникальные имена трёх каналов, через которые будет осуществляться взаимодействие Web-сервера и сервера тестирования. Получив имена каналов, сервер тестирования устанавливает соединения с каждым каналом и переходит в режим ожидания запроса на тестирование решения пользователя. Web-сервер содержит пул подключённых к нему серверов тестирования, и при получении решения от пользователя выбирает один из свободных серверов тестирования и отправляет ему запрос.
Таблица 1 – Структура пакета Setup
Имя поля |
Тип поля |
Описание |
QueryChanName |
строка |
Имя канала запросов |
AnswerChanName |
строка |
Имя канала ответов |
TaskChanName |
строка |
Имя канала проверочных данных |
Канал запросов направлен от Web-сервера к серверу тестирования. Из него сервер тестирования получает пакеты Query, структура которых описана в таблице 2. Каждый пакет описывает одно решение, отправленное на проверку. Задача, соответствующая решению, определяется значением поля Uid. Это значение является ключом, по которому сервер тестирования получает проверочные данные из кэша задач. Сервер тестирования компилирует полученное решение с использованием компилятора, определяемого значением поля Language запроса, и если компиляция прошла успешно, прогоняет решение через набор тестов, используя для этого «песочницу». При этом каждый запуск решения ограничен по времени выполнения и по объёму используемой оперативной памяти.
Отдельного обсуждения заслуживает поле Task в составе пакета Query. Оно либо пусто, либо содержит массив байт, в котором находятся сжатые в tar.gz проверочные данные для задачи. Web-сервер заполняет это поле только по требованию сервера тестирования. Происходит это следующим образом: если сервер тестирования не находит в кэше задач проверочные данных для задачи, решение которой находится в запросе, он отправляет Web-серверу ответ, содержащий вердикт UNKNOWN_TASK, и тогда Web-сервер повторно отправляет запрос, заполнив в нём поле Task.
Таблица 2 – Структура пакета Query
Имя поля |
Тип поля |
Описание |
Uid |
64-разрядное целое число |
Уникальный идентификатор задачи |
TimeLimit |
32-разрядное целое число |
Максимальное время работы решения (в миллисекундах) |
MemoryLimit |
32-разрядное целое число |
Максимальный размер данных в адресном пространстве процесса, в котором запущено решение (в Кб) |
Language |
32-разрядное целое число |
Идентификатор языка, на котором написано решение |
Solution |
строка |
Исходный код решения |
Task |
массив байт |
Проверочные данные для задачи (в tar.gz) |
Канал ответов направлен от сервера тестирования к Web-серверу. В него сервер тестирования записывает свой вердикт в виде пакета Answer, структура которого описана в таблице 3. Поле Result пакета Answer содержит код, описывающий вердикт сервера тестирования (таблица 4). Если решение успешно откомпилировалось, но не прошло какой-то тест, то данные этого теста также помещаются в пакет.
Таблица 3 – Структура пакета Answer
Имя поля |
Тип поля |
Описание |
Result |
32-разрядное целое число |
Код результата |
CompilerOutput |
строка |
Сообщения компилятора |
FailedTest |
строка |
Входные данные для теста, не пройденного решением |
SolutionOutput |
строка |
Ошибочный результат выполнения решения |
RightOutput |
строка |
Правильный результат для теста, не пройденного решением. |
Таблица 4 – Коды вердикта сервера тестирования
Код |
Описание |
OK |
Компиляция решения выполнена успешно, все тесты пройдены. |
COMPILATION_ERROR |
Решение не прошло компиляцию, сообщения компилятора помещены в поле CompilerOutput. |
WRONG_ANSWER |
Результат выполнения решения на одном из тестов был проанализирован и признан ошибочным. |
PRESENTATION_ERROR |
Формат результата выполнения решения на одном из тестов неправилен и не может быть разобран сервером тестирования. |
TIME_LIMIT_EXCEEDED |
Выполнение решения на одном из тестов было прервано из-за превышения лимита времени. |
MEMORY_LIMIT_EXCEEDED |
Выполнение решения на одном из тестов было прервано из-за превышения лимита памяти. |
RUN_TIME_ERROR |
В процессе выполнения решения на одном из тестов произошла ошибка времени выполнения. |
INTERNAL_ERROR |
Внутренняя ошибка сервера. |
UNKNOWN_TASK |
Проверочные данные для задачи отсутствуют в кэше задач. |