MikeMirzayanov's blog

By MikeMirzayanov, 11 years ago, In Russian

Это уже стало доброй традицией, что когда я еду в поезде или нахожусь в командировке, то вношу изменения в testlib. Видимо, причина тому — невозможность погрузиться в сложную задачу с большим контекстом по Polygon/Codeforces, но желание сделать что-то полезное здесь и сейчас.

Напоминаю, что testlib — мощная библиотека и стандард де-факто для подготовки задач по программированию, если вы используете С++. С помощью testlib можно значительно упростить подготовку: валидаторов, генераторов, чекеров и интеракторов. Все эти программы ниже буду называть testlib-программами.

Вот код ревизии, о которой идет речь. А вот ссылка с подсвеченными изменениями, которая может заменить весь текст поста. Как только будет понятно, что последние изменения финализированы, то будет выпущен новый релиз и обновим testlib в Полигоне. Выпущен релиз 0.9.4, который доступен со страницы загрузок.

Короткий список основных изменений:

Улучшена совместимость с компиляторами

В промежуточных версиях были сложности с компиляцией testlib-программ в Borland C++, некоторых версиях g++ и Microsoft Visual Studio C++. Всё это было исправлено, текущая версия компилируется в Borland C++ 5.6.4, g++ версий 0.7.2 и 0.8.1, Microsoft VS C++ версий 2005, 2008, 2010 и 2012.

Производительность

Сделаны некоторые улучшения производительности. Например, ранее ensure (функция наподобие assert, приводит к аварийному останову testlib-программы, если аргумент равен false) приводил к созданию std::string даже, если вызов не приводил к аварийному останову.

Другое

  • У InStream больше нет доступных конструктора копирования и оператора присваивания. Это запрещает передавать объекты InStream по значению, ведь такая передача является логической ошибкой.
  • Добавлена функция disableFinalizeGuard(), чтобы отключить проверку вызова quitf в чекере и readEof в валидаторе перед выходом. Честно говоря, так и не понял зачем это надо было, но просили. Видимо, для каких-то хакерских целей из-за нетипичного использования testlib.
  • Добавлена функция expectedButFound для выхода с красивым сообщением. Вот примеры использования: expectedButFound(_wa, 5, 6) — будет выход с _wa и сообщением типа expected 5, but found 6, еще пример expectedButFound(_wa, 5, 6, "test case %d", 13) завершит работу с _wa и сообщением test case 13: expected 5, but found 6. Умеет сам красиво форматировать вещественные числа и сокращать сверхдлинные строки (добавлять в середине многоточие).

Создание InStream от строки

Теперь всю мощь InStream можно применять для произвольной строки. Т.е. вычитывать данные с помощью всяких readToken и проч. можно из произвольной строки. При создании InStream следует указать тот поток, от которого унаследуется поведение в случае ошибок. Например, InStream yesOrNo(inf, "YES"). Может быть полезно в случае сложных разборов вывода (например, если удобно прочесть строку, что-то в ней проверить, а потом еще попарсить ее с помощью InStream).

Warnings

Неугомонный PavelKunyavskiy помог локализовать и закрыть пачку warnings в g++. В настоящее время testlib не порождает warnings даже при ключах -Wall -Wextra -Wconversion.

Опциональный новый вердикт: Unexpected EOF

Если скомпилировать с -DENABLE_UNEXPECTED_EOF, то при попытки прочитать что-то из потока произойдет вердикт unexpected eof, если этого чего-то в потоке нет. Код выхода по умолчанию: 8. Полезно для интеракторов, так как иначе они могут путать некоторые вердикты.

Исправления ошибок

  • выход с вердиктом о частичном решении класса 1, т.е. так: quitf(_pc(1), "...message..."); приводил к неправильному поведению;
  • генератор случайных чисел всегда оставлял один из битов нулевым (имеет значение только при генерации long long). Теперь рекомендуется явно указывать текущую версию генератора случайных чисел в генераторе вот так registerGen(argc, argv, 1);
  • было некорректное поведение при чтении nan в качестве double на некоторых компиляторах;
  • иногда неправильно обрабатывался дефис в паттернах для валидаторов/генераторов.
  • Vote: I like it
  • +43
  • Vote: I do not like it