perlhack
СОДЕРЖАНИЕ
- NAME
- DESCRIPTION
- СУПЕР БЫСТРОЕ РУКОВОДСТВО ПО ИСПРАВЛЕНИЮ
- СООБЩЕНИЕ ОБ ОШИБКАХ
- РАЗРАБОТЧИКИ PERL 5
- ПОЛУЧЕНИЕ ИСТОЧНОГО КОДА PERL
- ИСПРАВЛЕНИЕ PERL
- Отправка исправлений
- Получение одобрения исправления
- Исправление основного модуля
- Обновление perldelta
- Что делает патч хорошим?
- Соответствует ли концепция общим целям Perl?
- Где реализация?
- Обратная совместимость
- Можно ли сделать это модулем?
- Достаточно ли универсальна функция?
- Может ли это привести к новым ошибкам?
- Насколько это велико?
- Препятствует ли это другим желаемым функциям?
- Насколько надежна реализация?
- Достаточно ли универсальна реализация для переноса?
- Протестирована ли реализация?
- Достаточно ли документации?
- Есть ли другой способ сделать это?
- Создает ли это слишком много работы?
- Исправления говорят громче слов
- ТЕСТИРОВАНИЕ
- ДОПОЛНИТЕЛЬНОЕ ЧТЕНИЕ ДЛЯ ХАКЕРОВ
- ТЕСТЕРЫ CPAN И КУРИЛЬЩИКИ PERL
- ЧТО ДАЛЬШЕ?
- AUTHOR
NAME
perlhack - Как работать над Perl
DESCRIPTION
В этом документе объясняется, как работает разработка Perl. Он включает в себя подробную информацию о списке рассылки Perl 5 Porters, репозитории Perl, системе отслеживания ошибок Perl, рекомендациях по исправлению ошибок и комментариях о философии разработки Perl.
СУПЕР БЫСТРОЕ РУКОВОДСТВО ПО ИСПРАВЛЕНИЮ
Если вы просто хотите отправить одно небольшое исправление, например, исправление pod, тест для ошибки, исправления комментариев и т. д., это легко! Вот как:
-
Проверьте репозиторий исходного кода
Исходный код perl находится в репозитории git. Вы можете клонировать репозиторий с помощью следующей команды:
% git clone https://github.com/Perl/perl5.git perl -
Убедитесь, что вы следуете последним рекомендациям
В случае, если рекомендации в этом руководстве были недавно обновлены, прочитайте последнюю версию непосредственно из исходного кода perl:
% perldoc pod/perlhack.pod -
Создайте ветку для вашего изменения
Создайте ветку на основе blead, чтобы зафиксировать ваше изменение, которое позже будет использовано для отправки в систему отслеживания ошибок Perl.
% git checkout -b mychange -
Внесите изменения
Хак, хак, хак. Имейте в виду, что Perl работает на многих разных платформах, с различными операционными системами, которые имеют разные возможности, различные организации файловых систем и даже различные кодировки символов. perlhacktips дает советы по этому поводу.
-
Проверьте свои изменения
Вы можете запустить все тесты с помощью следующих команд:
% ./Configure -des -Dusedevel % make testПродолжайте работу, пока тесты не пройдут.
-
Зафиксируйте свои изменения
Фиксация вашей работы сохранит изменения в вашей локальной системе:
% git commit -a -m 'Commit message goes here'Убедитесь, что сообщение о фиксации описывает ваше изменение в одном предложении. Например, «Исправлены орфографические ошибки в perlhack.pod».
-
Отправьте изменения в систему отслеживания ошибок Perl
Следующим шагом является отправка вашего исправления в систему отслеживания ошибок ядра Perl.
Создайте GitHub fork репозитория perl5 и добавьте его как удаленный, если вы еще этого не сделали, как описано в документации GitHub по адресу https://help.github.com/en/articles/working-with-forks.
% git remote add fork git@github.com:MyUser/perl5.gitДля получения дополнительной информации см. "Подключение к GitHub с помощью SSH".
Если вы предпочитаете использовать URL-адрес HTTPS для вашего
git pushсм. "Клонирование с использованием URL-адресов HTTPS".% git remote add fork https://github.com/MyUser/perl5.gitЗатем отправьте свою новую ветку в свой fork.
% git push -u fork mychangeНаконец, создайте запрос на вытягивание на GitHub из вашей ветки в blead, как описано в документации GitHub по адресу https://help.github.com/en/articles/creating-a-pull-request-from-a-fork.
-
Спасибо
Разработчики ценят время, которое вы потратили на улучшение Perl. Спасибо!
-
Благодарность
Все участники проекта упомянуты (по имени и адресу электронной почты) в файле AUTHORS, который является частью дистрибутива perl, а также в истории коммитов Git.
Если вы не хотите, чтобы вас включили в файл AUTHORS, просто сообщите нам об этом. В противном случае мы будем считать вашу отправку исправления разрешением на указание вас в файле AUTHORS.
-
В следующий раз
В следующий раз, когда вы захотите внести исправление, вам нужно начать с последней версии perl в чистом состоянии. Убедитесь, что у вас нет локальных изменений или добавленных файлов в вашей выписке perl, которые вы хотите сохранить, затем выполните следующие команды:
% git checkout blead % git pull % git reset --hard origin/blead % git clean -dxf
СООБЩЕНИЕ ОБ ОШИБКАХ
Если вы хотите сообщить об ошибке в Perl или просмотреть существующие ошибки и исправления Perl, используйте систему отслеживания ошибок GitHub по адресу https://github.com/perl/perl5/issues.
Пожалуйста, проверьте архив списка perl5-porters (см. ниже) и/или систему отслеживания ошибок, прежде чем отправлять отчет об ошибке. Часто вы обнаружите, что об ошибке уже сообщалось.
Вы можете войти в систему отслеживания ошибок и прокомментировать существующие отчеты об ошибках. Если у вас есть дополнительная информация о существующей ошибке, пожалуйста, добавьте ее. Это поможет разработчикам исправить ошибку.
РАЗРАБОТЧИКИ PERL 5
Список рассылки perl5-porters (p5p) — это место, где поддерживается и разрабатывается стандартный дистрибутив Perl. Люди, которые поддерживают Perl, также называются «разработчиками Perl 5», «p5p» или просто «разработчиками».
Поисковый архив списка доступен по адресу https://markmail.org/search/?q=perl5-porters. Существует также архив по адресу https://archive.develooper.com/perl5-porters@perl.org/.
Рассылка perl-changes
Список рассылки perl5-changes получает копию каждого исправления, которое отправляется в ветки обслуживания и разработки репозитория perl. См. https://lists.perl.org/list/perl5-changes.html для получения информации о подписке и архиве.
#p5p на IRC
Многие разработчики также активны на канале irc://irc.perl.org/#p5p. Не стесняйтесь присоединиться к каналу и задавать вопросы о работе над ядром Perl.
ПОЛУЧЕНИЕ ИСТОЧНОГО КОДА PERL
Весь исходный код Perl хранится централизованно в репозитории Git на github.com. Репозиторий содержит множество версий Perl, начиная с Perl 1, и все версии из Perforce, предыдущей системы управления версиями.
Для получения гораздо более подробной информации об использовании git с репозиторием Perl, пожалуйста, см. perlgit.
Чтение через Git
Вам потребуется копия Git для вашего компьютера. Вы можете получить копию репозитория с помощью протокола git:
% git clone git@github.com:Perl/perl5.git perl Это клонирует репозиторий и создает локальную копию в каталоге perl.
Если вы не можете использовать протокол git из-за проблем с брандмауэром, вы также можете клонировать через http:
% git clone https://github.com/Perl/perl5.git perl Доступ для чтения через веб
Вы можете получить доступ к репозиторию через веб. Это позволяет вам просматривать дерево, видеть последние коммиты, подписываться на уведомления репозитория, искать конкретные коммиты и многое другое. Вы можете получить к нему доступ по адресу https://github.com/Perl/perl5.
Запись через git
Если у вас есть бит коммита, пожалуйста, см. perlgit для получения более подробной информации об использовании git.
ВНЕСЕНИЕ ИЗМЕНЕНИЙ В PERL
Если вы планируете выполнить более обширную работу, чем простое исправление, мы рекомендуем вам ознакомиться с документацией ниже. Это поможет вам сосредоточить свою работу и упростит внесение ваших исправлений в исходный код Perl.
Отправка исправлений
Если у вас есть небольшое исправление для отправки, пожалуйста, отправьте его через рабочий процесс GitHub Pull Request. Вы также можете отправлять исправления в список p5p.
Исправления проверяются и обсуждаются на GitHub или в списке p5p. Простые, бесспорные исправления обычно применяются без каких-либо обсуждений. После применения исправления тикет будет обновлен, и вы получите электронное письмо.
В других случаях исправлению потребуется дополнительная работа или обсуждение. Вам предлагается участвовать в обсуждении и отстаивать свое исправление. Иногда ваше исправление может затеряться в суматохе. Целесообразно отправить напоминание по электронной почте в p5p, если в течение месяца не было предпринято никаких действий. Пожалуйста, помните, что разработчики Perl 5 — это все волонтеры, и будьте вежливы.
Изменения всегда применяются непосредственно к основной ветке разработки, называемой "blead". Некоторые исправления могут быть перенесены в ветку обслуживания. Если вы считаете, что ваше исправление подходит для ветки обслуживания (см. "ВЕТКИ ОБСЛУЖИВАНИЯ" в perlpolicy), пожалуйста, объясните почему, когда вы его отправите.
Получение принятия вашего исправления
Если вы отправляете исправление кода, есть несколько вещей, которые вы можете сделать, чтобы помочь разработчикам Perl 5 принять ваше исправление.
Стиль патча
Используя рабочий процесс GitHub Pull Request, ваш патч будет автоматически доступен в подходящем формате. Если вы хотите отправить патч в список p5p для проверки, убедитесь, что вы создали его соответствующим образом.
Если вы использовали git для проверки исходного кода Perl, то использование git format-patch создаст патч в стиле, подходящем для Perl. Команда format-patch создает один файл патча для каждого сделанного вами коммита. Если вы предпочитаете отправлять один патч для всех коммитов, вы можете использовать git diff.
% git checkout blead
% git pull
% git diff blead my-branch-name Это создает патч на основе разницы между blead и вашей текущей веткой. Важно убедиться, что blead обновлен перед созданием diff, поэтому мы сначала вызываем git pull.
Мы настоятельно рекомендуем использовать git, если это возможно. Это упростит вашу жизнь, а также нашу.
Однако, если вы не используете git, вы все равно можете создать подходящий патч. Вам потребуется чистая копия исходного кода Perl для сравнения. Разработчики предпочитают унифицированные diff. Используя GNU diff, вы можете создать diff, например:
% diff -Npurd perl.pristine perl.mine Убедитесь, что вы make realclean в вашей копии Perl, чтобы удалить любые артефакты сборки, иначе вы можете получить запутанный результат.
Сообщение о коммите
При создании каждого патча, который вы намереваетесь отправить в ядро Perl, важно написать хорошее сообщение о коммите. Это особенно важно, если ваша отправка будет состоять из серии коммитов.
Первая строка сообщения о коммите должна быть кратким описанием без точки. Она не должна быть длиннее темы электронного письма, 50 символов — хорошее правило.
Многие инструменты Git (Gitweb, GitHub, git log --pretty=oneline, ...) будут отображать только первую строку (обрезанную до 50 символов) при представлении сводки коммитов.
Сообщение о коммите должно включать описание проблемы, которую исправляет патч, или новой функциональности, которую добавляет патч.
Как общее правило, ваше сообщение о коммите должно помочь программисту, знающему ядро Perl, быстро понять, что вы пытались сделать, как вы пытались это сделать и почему это изменение важно для Perl.
-
Зачем
Ваше сообщение о коммите должно описывать, почему важно изменение, которое вы вносите. Когда кто-то посмотрит на ваше изменение через шесть месяцев или шесть лет, ваш замысел должен быть ясен.
Если вы устареваете функцию с целью последующего упрощения другого фрагмента кода, скажите об этом. Если вы исправьте проблему производительности или добавляете новую функцию для поддержки другого фрагмента ядра, упомяните об этом.
-
Что
Ваше сообщение о коммите должно описывать, какую часть ядра Perl вы меняете и что вы ожидаете от вашего патча.
-
Как
Хотя это не обязательно для изменений документации, новых тестов или тривиальных исправлений, часто стоит объяснить, как работает ваше изменение. Даже если это понятно вам сегодня, это может быть не ясно разработчику в следующем месяце или в следующем году.
Сообщение о коммите не предназначено для замены комментариев в вашем коде. Сообщения о коммите должны описывать внесенное вами изменение, а комментарии к коду должны описывать текущее состояние кода.
Если вы только что реализовали новую функцию, полную документации, тестов и хорошо закомментированного кода, часто будет достаточно краткого сообщения о коммите. Однако, если вы только что изменили один символ глубоко в парсере или лексическом анализаторе, вам может потребоваться написать небольшой роман, чтобы убедиться, что будущие читатели понимают, что вы сделали и почему вы это сделали.
Комментарии, Комментарии, Комментарии
Обязательно адекватно комментируйте свой код. Хотя комментирование каждой строки не обязательно, все, что использует побочные эффекты операторов, создает изменения, которые будут ощущаться за пределами исправленной функции, или что может показаться другим запутанным, должно быть задокументировано. Если вы собираетесь ошибаться, лучше ошибаться, добавляя слишком много комментариев, чем слишком мало.
Лучшие комментарии объясняют, почему код делает то, что он делает, а не что он делает.
Стиль
В общем, пожалуйста, следуйте конкретному стилю кода, который вы исправьте.
В частности, следуйте этим общим рекомендациям по исправлению исходных кодов Perl:
-
4-значные отступы для кода, 2-значные отступы для вложенных CPP
#defines, с 8-значными табуляциями. -
Используйте пробелы для отступов, а не символы табуляции.
База кода представляет собой смесь табуляций и пробелов для отступов, и мы переходим только к пробелам. Преобразование строк, которые вы исправляєте, из 8-значных табуляций в пробелы поможет этой миграции.
-
Старайтесь не превышать 79 столбцов
В общем, мы нацелены на строки из 80 столбцов. Когда придерживание 80 столбцов приведет к мучительному коду или переделке, можно идти дольше. Старайтесь свести к минимуму превышение 80.
-
Прототипы ANSI C
-
Необъятные else и стиль "K&R" для отступа управляющих конструкций
-
Нет комментариев в стиле C++ (//)
-
Отмечайте места, которые нужно пересмотреть, с помощью XXX (и пересматривайте часто!)
-
Открывающая фигурная скобка выравнивается с "if", когда условие занимает несколько строк; должна быть в конце строки в противном случае
-
В определениях функций имя начинается в столбце 0 (тип возвращаемого значения находится на предыдущей строке)
-
Один пробел после ключевых слов, за которыми следуют скобки, без пробела между именем функции и следующей скобкой
-
Избегайте присваиваний в условных выражениях, но если они неизбежны, используйте дополнительные скобки, например, "if (a && (b = c)) ..."
-
"return foo;" вместо "return(foo);"
-
"if (!foo) ..." вместо "if (foo == FALSE) ..." и т.д.
-
Не объявляйте переменные с помощью "register". Это может быть контрпродуктивно для современных компиляторов и устарело в C++, под которым регулярно компилируется исходный код Perl.
-
Встроенные функции, которые находятся в заголовках, доступных для кода XS, должны иметь возможность компилироваться без предупреждений с часто используемыми дополнительными флагами компиляции, такими как
-Wswitch-defaultgcc, которые выдают предупреждение, когда оператор switch не имеет случая "default". Использование этих дополнительных флагов позволяет обнаружить потенциальные проблемы в легальном коде C и часто используется агрегаторами Perl, такими как дистрибуторы Linux.
Тестовый набор
Если ваш патч изменяет код (а не просто изменяет документацию), вы также должны включить один или несколько тестовых случаев, которые иллюстрируют ошибку, которую вы исправляєте, или проверяют новую функциональность, которую вы добавляете. В общем, вам следует обновить существующий тестовый файл, а не создавать новый.
Ваши дополнения к тестовому набору должны в целом соответствовать следующим рекомендациям (любезно предоставленным Gurusamy Sarathy <gsar@activestate.com>):
-
Знайте, что вы тестируете. Прочитайте документацию и исходный код.
-
Стремитесь к неудаче, а не к успеху.
-
Строго интерпретируйте результаты.
-
Используйте несвязанные функции (это позволит выявить странные взаимодействия).
-
Используйте нестандартные идиомы (иначе вы не тестируете TIMTOWTDI).
-
Избегайте использования жестко закодированных тестовых чисел, когда это возможно (EXPECTED/GOT, найденные в t/op/tie.t, намного проще в обслуживании и обеспечивают лучшие отчеты об ошибках).
-
Выдавайте понятные сообщения об ошибках при сбое теста.
-
Избегайте использования qx// и system(), если вы не тестируете их. Если вы используете их, убедитесь, что вы охватываете _все_ платформы perl.
-
Удаляйте любые временные файлы, которые вы создаете.
-
Превращайте непредвиденные предупреждения в ошибки с помощью $SIG{__WARN__}.
-
Обязательно используйте библиотеки и модули, поставляемые с тестируемой версией, а не те, которые уже были установлены.
-
Добавьте комментарии к коду, объясняющие, что вы тестируете.
-
Сделайте обновление строки '1..42' ненужным. Или убедитесь, что вы обновили ее.
-
Тестируйте _все_ поведения данного оператора, библиотеки или функции.
Тестируйте все необязательные аргументы.
Тестируйте возвращаемые значения в различных контекстах (булево, скалярное, список, lvalue).
Используйте как глобальные, так и лексические переменные.
Не забывайте об исключительных, патологических случаях.
Внесение изменений в основной модуль
Это работает так же, как и исправление чего-либо еще, с одним дополнительным соображением.
Модули в каталоге cpan/ исходного дерева поддерживаются за пределами ядра Perl. Когда автор обновляет модуль, обновления просто копируются в ядро. См. документацию этого модуля или его список на https://metacpan.org/ для получения дополнительной информации о сообщении об ошибках и отправке исправлений.
В большинстве случаев исправления модулей в cpan/ должны отправляться вверх по потоку и не должны применяться к ядру Perl по отдельности. Если исправление файла в cpan/ абсолютно не может ждать, пока исправление будет внесено вверх по потоку, выпущено в CPAN и скопировано в blead, вы должны добавить (или обновить) запись CUSTOMIZED в файле Porting/Maintainers.pl, чтобы отметить, что локальное изменение было сделано. См. Porting/Maintainers.pl для получения более подробной информации.
Напротив, модули в каталоге dist/ поддерживаются в ядре.
Обновление perldelta
Для изменений, достаточно значительных, чтобы гарантировать запись pod/perldelta.pod, разработчики будут очень признательны, если вы отправите запись delta вместе с вашим фактическим изменением. К значительным изменениям относятся, помимо прочего:
-
Добавление, устаревание или удаление основных функций
-
Добавление, устаревание, удаление или обновление основных или двойных модулей
-
Добавление новых основных тестов
-
Исправление проблем безопасности и видимых пользователю ошибок в ядре
-
Изменения, которые могут нарушить существующий код, как на уровне perl, так и на уровне C
-
Значительные улучшения производительности
-
Добавление, удаление или существенное изменение документации в каталоге pod/
-
Важные изменения, специфичные для платформы
Пожалуйста, убедитесь, что вы добавили запись perldelta в правильный раздел в pod/perldelta.pod. Дополнительная информация о том, как писать хорошие записи perldelta, доступна в разделе Style Porting/how_to_write_a_perldelta.pod.
Что делает патч хорошим?
Новые функции и расширения языка могут быть спорными. Нет конкретного набора критериев, определяющих, какие функции добавляются, но вот некоторые вопросы, которые следует учитывать при разработке патча:
Соответствует ли концепция общим целям Perl?
Наши цели включают, но не ограничиваются:
-
Быстро, просто и полезно.
-
Сохранять функции/концепции максимально ортогональными.
-
Отсутствие произвольных ограничений (платформы, размеры данных, культуры).
-
Сохранять его открытым и интересным для использования/патчинга/защиты Perl повсюду.
-
Ассимилировать новые технологии или создавать мосты к ним.
Где реализация?
Все разговоры в мире бесполезны без реализации. Почти в каждом случае от человека или людей, которые выступают за новую функцию, ожидается, что они будут теми, кто ее реализует. Портеры, способные кодировать новые функции, имеют свои собственные планы и не доступны для реализации вашей (возможно, хорошей) идеи.
Обратная совместимость
Нарушение существующих программ Perl — это кардинальный грех. Новые предупреждения могут быть спорными — некоторые говорят, что программа, которая выдает предупреждения, не сломана, а другие говорят, что сломана. Добавление ключевых слов может привести к поломке программ, изменение смысла существующих последовательностей токенов или функций может привести к поломке программ.
Ядро Perl 5 включает механизмы, которые помогают портерам сделать несовместимые с обратной совместимостью изменения более совместимыми, такие как модули feature и deprecate. Пожалуйста, используйте их, когда это уместно.
Может ли это быть модулем?
Perl 5 имеет механизмы расширения, модули и XS, специально для того, чтобы избежать необходимости постоянно изменять интерпретатор Perl. Вы можете написать модули, которые экспортируют функции, вы можете дать этим функциям прототипы, чтобы их можно было вызывать как встроенные функции, вы даже можете написать код XS, чтобы возиться со структурами данных времени выполнения интерпретатора Perl, если вы хотите реализовать действительно сложные вещи.
Всякий раз, когда это возможно, новые функции должны быть созданы в виде прототипа в модуле CPAN, прежде чем они будут рассмотрены для ядра.
Является ли функция достаточно универсальной?
Это то, что хочет добавить в язык только отправитель, или это широко полезно? Иногда, вместо добавления функции с узким фокусом, портеры могут решить подождать, пока кто-то реализует более обобщенную функцию.
Может ли это привести к появлению новых ошибок?
Радикальная переработка больших фрагментов интерпретатора Perl может привести к появлению новых ошибок.
Насколько это большое изменение?
Чем меньше и более локализовано изменение, тем лучше. Аналогично, серия небольших патчей намного предпочтительнее одного большого патча.
Препятствует ли это другим желаемым функциям?
Патч, скорее всего, будет отклонен, если он закроет будущие пути развития. Например, патч, который дал бы истинное и окончательное толкование прототипов, скорее всего, будет отклонен, потому что все еще есть варианты для будущего прототипов, которые не были рассмотрены.
Надежна ли реализация?
Хорошие патчи (компактный код, полный, правильный) имеют больше шансов быть принятыми. Небрежные или неправильные патчи могут быть отложены до тех пор, пока не будут внесены исправления, или они могут быть полностью отброшены без дальнейшего уведомления.
Достаточно ли универсальна реализация для обеспечения переносимости?
Худшие патчи используют функции, специфичные для системы. Крайне маловероятно, что непереносимые дополнения к языку Perl будут приняты.
Протестирована ли реализация?
Патчи, которые изменяют поведение (исправление ошибок или внедрение новых функций), должны включать регрессионные тесты, чтобы убедиться, что все работает как ожидалось.
Без тестов, предоставленных исходным автором, как кто-либо другой, кто изменяет perl в будущем, может быть уверен, что он невольно не сломал поведение, реализованное патчем? И без тестов, как автор патча может быть уверен, что его/ее тяжелая работа, вложенная в патч, не будет случайно выброшена кем-то в будущем?
Достаточно ли документации?
Патчи без документации, вероятно, плохо продуманы или неполны. Никакие функции не могут быть добавлены или изменены без документации, поэтому отправка патча для соответствующих документов pod, а также исходного кода, имеет важное значение.
Есть ли другой способ сделать это?
Ларри сказал: «Хотя слоган Perl — There's More Than One Way to Do It, я колеблюсь, создавая 10 способов сделать что-то». Однако этот эвристический метод сложно использовать — то, что для одного человека является существенным дополнением, для другого — бессмысленным мусором.
Создает ли это слишком много работы?
Работа для коммиттеров, работа для программистов Perl, работа для авторов модулей, ... Perl должен быть простым.
Патчи говорят громче слов
Рабочий код всегда предпочтительнее идей из области фантастики. Патч для добавления функции имеет гораздо больше шансов попасть в язык, чем случайный запрос функции, независимо от того, насколько сильно аргументируется этот запрос. Это связано с вопросом «Будет ли это полезно?», так как тот факт, что кто-то потратил время на создание патча, демонстрирует сильное желание использовать эту функцию.
ТЕСТИРОВАНИЕ
Ядро использует тот же стиль тестирования, что и остальная часть Perl, простой прогон «ok/not ok» через Test::Harness, но есть несколько особых моментов.
Есть три способа написать тест в ядре: Test::More, t/test.pl и ad hoc print $test ? "ok 42\n" : "not ok 42\n". Решение о том, какой из них использовать, зависит от того, над какой частью тестового набора вы работаете. Это мера для предотвращения сбоя высокого уровня (например, поломки Config.pm) от вызова сбоя тестов базовой функциональности.
Библиотека t/test.pl предоставляет некоторые функции Test::More, но избегает загрузки большинства модулей и использует как можно меньше основных функций.
Если вы пишете свой собственный тест, используйте Test Anything Protocol.
-
t/base, t/comp и t/opbasic
Поскольку мы не знаем, работает ли
require, или даже подпрограммы, используйте для этих трех ad hoc тесты. Действуйте осторожно, чтобы избежать использования тестируемой функции. Тесты в t/opbasic, например, были размещены там, а не в t/op, потому что они проверяют функциональность, которую t/test.pl предполагает уже продемонстрированную как работающую. -
Все остальные подкаталоги t/
Теперь, когда базовые require() и подпрограммы протестированы, вы можете использовать библиотеку t/test.pl.
Вы также можете условно использовать определенные библиотеки, такие как Config, но обязательно корректно пропустите тест, если его нет.
-
Файлы тестов, не найденные в t/
Эта категория включает файлы .t в подкаталогах, таких как dist, ext и lib. Поскольку ядро Perl теперь протестировано, можно и теперь следует использовать Test::More. Вы также можете использовать полный набор основных модулей в тестах. (Как указано в разделе "Исправление основного модуля" выше, изменения в файлах .t, найденных в cpan/, следует отправлять основным разработчикам этих модулей.)
Когда вы говорите «make test», Perl использует программу t/TEST для запуска тестового набора (за исключением Win32, где вместо него используется t/harness). Все тесты выполняются из каталога t/, а не из каталога, содержащего тест. Это вызывает некоторые проблемы с тестами в lib/, поэтому здесь есть возможность для некоторых патчей.
Вы должны быть втройне внимательны к проблемам кроссплатформенности. Обычно это сводится к использованию File::Spec, избеганию таких вещей, как fork() и system(), если это абсолютно необходимо, и не предполагая, что данный символ имеет определенное порядковое значение (кодовую точку) или что его представление UTF-8 состоит из определенных байтов.
Доступно несколько функций для указания символов и кодовых точек переносимым способом в тестах. Всегда предварительно загруженные функции utf8::unicode_to_native() и ее обратная utf8::native_to_unicode() принимают кодовые точки и переводят соответствующим образом. Файл t/charset_tools.pl содержит несколько полезных функций. Он содержит версии двух предыдущих функций, которые принимают строки в качестве входных данных — а не отдельные числовые кодовые точки: uni_to_native() и native_to_uni(). Если вы должны посмотреть на отдельные байты, составляющие строку, закодированную в UTF-8, byte_utf8a_to_utf8n() принимает в качестве входных данных строку этих байтов, закодированных для платформы ASCII, и возвращает эквивалентную строку на собственной платформе. Например, byte_utf8a_to_utf8n("\xC2\xA0") возвращает последовательность байтов на текущей платформе, которые образуют UTF-8 для U+00A0, поскольку "\xC2\xA0" являются байтами UTF-8 на платформе ASCII для этой кодовой точки. Эта функция возвращает "\xC2\xA0" на платформе ASCII и "\x80\x41" на платформе EBCDIC 1047.
Но проще всего, если символ можно указать как литерал, например "A" или "%", использовать его; если он не указан так конкретно, вы можете использовать \N{}, если побочные эффекты не вызывают проблем. Просто укажите все свои символы в шестнадцатеричном формате, используя \N{U+ZZ} вместо \xZZ. \N{} — это имя Unicode, поэтому оно всегда дает вам символ Unicode. \N{U+41} — это символ, чья кодовая точка Unicode равна 0x41, следовательно, это 'A' на всех платформах. Побочные эффекты следующие:
-
Они выбирают правила Unicode. Это означает, что в строках в двойных кавычках строка всегда преобразуется в UTF-8, чтобы принудительно выполнить интерпретацию Unicode (вы можете
utf8::downgrade()после этого, чтобы преобразовать обратно в не-UTF8, если это возможно). В шаблонах регулярных выражений преобразование не выполняется, но если модификатор набора символов в противном случае был бы/d, он изменяется на/u. -
Если вы используете форму
\N{character name}, модуль charnames загружается автоматически. Это может быть неподходящим для того уровня тестирования, который вы выполняете.
Если вы тестируете локали (см. perllocale), есть вспомогательные функции в t/loc_tools.pl, которые позволяют вам видеть, какие локали доступны на текущей платформе.
Специальные make test цели
Существуют различные специальные цели make, которые могут быть использованы для тестирования Perl немного иначе, чем стандартная цель "test". Не все из них ожидаемо дают 100% успешный результат. Многие из них имеют несколько псевдонимов, и многие из них недоступны на некоторых операционных системах.
-
test_porting
Это запускает некоторые базовые тесты работоспособности на исходном дереве и помогает обнаружить основные ошибки, прежде чем вы отправите патч.
-
minitest
Запускает miniperl на тестах t/base, t/comp, t/cmd, t/run, t/io, t/op, t/uni и t/mro.
miniperl - это минималистичный perl, созданный для загрузки расширений, утилит, документации и т.д. Он не поддерживает динамическую загрузку и, в зависимости от этапа процесса сборки, будет иметь доступ только к ограниченному набору основных модулей. miniperl не предназначен для повседневного использования.
-
test.valgrind check.valgrind
(Только в Linux) Запускает все тесты с использованием инструмента для обнаружения утечек памяти и некорректного доступа к памяти "valgrind". Файлы журнала будут названы testname.valgrind.
-
test_harness
Запускает набор тестов с управляющей программой t/harness вместо t/TEST. t/harness более сложен и использует модуль Test::Harness, поэтому использование этой цели теста предполагает, что perl в основном работает. Основное преимущество для наших целей заключается в том, что он выводит подробное резюме неудачных тестов в конце. Кроме того, в отличие от t/TEST, он не перенаправляет stderr в stdout.
Обратите внимание, что под Win32 t/harness всегда используется вместо t/TEST, поэтому специальной цели "test_harness" нет.
В процессе сборки под Unix вы можете использовать параметры TEST_ARGS и TEST_FILES для передачи аргументов в вызов базовой программы harness. Это означает, что, например, вы можете сделать
make test_harness TEST_ARGS="-v -re pat"что создаст, а затем запустит программу harness в подробном режиме для файлов, содержащих "pat". Или вы можете сделать
make test_harness TEST_ARGS="-torture" TEST_FILES="op/*.t"и запустить стресс-тесты на файлах, соответствующих шаблону "op/*.t".
В целевой среде "test" под Win32 вы можете использовать переменные среды TEST_SWITCHES и TEST_FILES для управления поведением t/harness. Это означает, что вы можете сказать
nmake test TEST_FILES="op/*.t" nmake test TEST_SWITCHES="-torture" TEST_FILES="op/*.t"Обратите внимание, что для совместимости с процессом сборки под Unix TEST_ARGS также может использоваться вместо традиционного аргумента TEST_SWITCHES.
-
test-notty test_notty
Устанавливает PERL_SKIP_TTY_TEST в true перед запуском обычного теста.
Параллельные тесты
Основной дистрибутив теперь может запускать свои регрессионные тесты параллельно на Unix-подобных и Windows платформах. В Unix, вместо запуска make test, установите TEST_JOBS в вашей среде на число тестов для параллельного запуска и запустите make test_harness. В оболочке типа Bourne это можно сделать так:
TEST_JOBS=3 make test_harness # Run 3 tests in parallel Переменная среды используется вместо параллельного make, потому что TAP::Harness должен иметь возможность сам планировать отдельные неконфликтующие тестовые скрипты, и нет стандартного интерфейса для make утилит для взаимодействия с их планировщиками заданий.
Тесты обычно запускаются в логическом порядке: сначала тесты работоспособности, затем основные тесты функциональности ядра Perl, затем тесты для нестандартных модулей. На многоядерных системах это может использовать аппаратные средства не так эффективно, как это возможно. Также указав
TEST_JOBS=19 PERL_TEST_HARNESS_ASAP=1 make -j19 test_harness вы сигнализируете, что хотите, чтобы тесты завершились за минимальное время. После завершения тестов работоспособности это приводит к тому, что остальные тесты максимально плотно упаковываются в доступные ядра. Это наиболее эффективно на более медленных многоядерных системах. Производительность была увеличена на 20% на устаревшей 24-ядерной системе; меньше - на более новых, более быстрых системах с меньшим количеством ядер.
Обратите внимание, что в приведенную выше команду добавлена -j параметр для make, чтобы вызвать параллельную компиляцию. Это может работать или не работать на вашей платформе.
Обычно данные о времени выполнения тестов хранятся в t/test_state, однако вы можете изменить это, используя другой файл, установив переменную среды PERL_TEST_STATE_FILE на другое значение или на ложное значение (0 или пустая строка), чтобы полностью отключить использование механизма состояния. Нет защиты от изменения формата файла состояния со временем, поэтому, если у вас возникнут какие-либо проблемы, связанные с этим файлом, вы можете удалить файл вручную, а затем позволить программе harness пересоздать его, хотя формат файла не изменяется часто, поэтому это не должно быть необходимо очень часто.
Запуск тестов вручную
Вы можете запустить часть тестового набора вручную, используя одну из следующих команд из директории t/:
./perl -I../lib TEST list-of-.t-files или
./perl -I../lib harness list-of-.t-files (Если вы не указываете тестовые скрипты, будет запущен весь тестовый набор.)
Использование t/harness для тестирования
Если вы используете harness для тестирования, у вас есть несколько доступных параметров командной строки. Аргументы следующие, и они должны появляться в указанном порядке, если используются вместе.
harness -v -torture -re=pattern LIST OF FILES TO TEST
harness -v -torture -re LIST OF PATTERNS TO MATCH Если LIST OF FILES TO TEST пропущен, список файлов получается из манифеста. Список файлов может включать подстановочные знаки оболочки, которые будут расширены.
-
-v
Запускает тесты в подробном режиме, чтобы вы могли видеть, какие тесты были запущены, и отладочный вывод.
-
-torture
Запускает стресс-тесты, а также обычный набор.
-
-re=PATTERN
Фильтрация списка файлов таким образом, чтобы все запускаемые тестовые файлы соответствовали PATTERN. Обратите внимание, что эта форма отличается от формы -re LIST OF PATTERNS ниже тем, что позволяет также указать список файлов.
-
-re LIST OF PATTERNS
Фильтрация списка файлов таким образом, чтобы все запускаемые тестовые файлы соответствовали /(LIST|OF|PATTERNS)/. Обратите внимание, что с этой формой шаблоны соединяются с помощью '|' и вы не можете указать список файлов, вместо этого тестовые файлы получаются из MANIFEST.
Вы можете запустить отдельный тест с помощью команды, подобной
./perl -I../lib path/to/foo.t за исключением того, что программы harness настраивают некоторые переменные среды, которые могут влиять на выполнение теста:
-
PERL_CORE=1
указывает, что мы запускаем этот тест как часть тестового набора ядра perl. Это полезно для модулей, которые имеют двойную жизнь на CPAN.
-
PERL_DESTRUCT_LEVEL=2
устанавливается в 2, если он ещё не установлен (см. "PERL_DESTRUCT_LEVEL" в perlhacktips).
-
PERL
(используется только t/TEST) если установлено, переопределяет путь к исполняемому файлу perl, который должен использоваться для запуска тестов (по умолчанию ./perl).
-
PERL_SKIP_TTY_TEST
если установлено, указывает пропустить тесты, которым нужен терминал. На самом деле он устанавливается автоматически Makefile, но также может быть принудительно установлен искусственно путем запуска 'make test_notty'.
Другие переменные среды, которые могут влиять на тесты
-
PERL_TEST_Net_Ping
Установка этой переменной запускает все тесты модулей Net::Ping, в противном случае некоторые тесты, которые взаимодействуют с внешним миром, пропускаются. См. perl58delta.
-
PERL_TEST_NOVREXX
Установка этой переменной пропускает тесты vrexx.t для OS2::REXX.
-
PERL_TEST_NUMCONVERTS
Это устанавливает переменную в op/numconvert.t.
-
PERL_TEST_MEMORY
Установка этой переменной включает тесты в t/bigmem/. Это должно быть установлено в число гигабайт памяти, доступной для тестирования, например,
PERL_TEST_MEMORY=4указывает, что тесты, требующие 4 ГБ доступной памяти, могут быть запущены безопасно.
См. также документацию для модулей Test и Test::Harness, для получения дополнительной информации о переменных среды, влияющих на тестирование.
Тестирование производительности
Файл t/perf/benchmarks содержит фрагменты кода perl, которые предназначены для тестирования производительности на различных версиях perl с помощью инструмента Porting/bench.pl. Если вы исправите или улучшите проблему производительности, вы можете добавить репрезентативный образец кода в файл, а затем запустить bench.pl для предыдущих и текущих версий perl, чтобы увидеть, какую разницу это дало и не замедлило ли что-либо ещё в результате.
Файл t/perf/opcount.t предназначен для проверки того, был ли определенный фрагмент кода скомпилирован в optree, содержащий указанное количество определенных типов операций. Это хорошо подходит для проверки того, действительно ли выполняются оптимизации, которые изменяют операции, например, преобразование операции aelem в операцию aelemfast.
Файлы t/perf/speed.t и t/re/speed.t предназначены для тестирования вещей, которые работают в тысячи раз медленнее, если определенная оптимизация сломана (например, кэш длины utf8 на длинных строках utf8). Добавьте тест, который обычно займет долю секунды, а в противном случае - минуты, вызывая истечение времени ожидания тестового файла при сбое.
Сборка perl на старых коммитах
В процессе работы над основным дистрибутивом Perl может возникнуть необходимость настроить, собрать и протестировать perl на старом коммите. Иногда make будет давать сбой в этом процессе. Если это произойдет, вы можете спасти ситуацию, используя библиотеку Devel::PatchPerl из CPAN (не включен в ядро), чтобы привести исходный код в этом коммите в состояние, пригодное для сборки.
Вот реальный пример, взятый из работы, проделанной для решения perl #10118. Использование Porting/bisect.pl определило коммит ba77e4cc9d1ceebf472c9c5c18b2377ee47062e6 как коммит, в котором была исправлена ошибка. Для подтверждения разработчик P5P хотел настроить и собрать perl на коммите ba77e4c^ (предположительно "плохом"), а затем на ba77e4c (предположительно "хорошем"). Была предпринята обычная настройка и сборка:
$ sh ./Configure -des -Dusedevel
$ make test_prep make, однако, завершилась ошибкой с выводом (фрагмент) следующим:
cc -fstack-protector -L/usr/local/lib -o miniperl \
gv.o toke.o perly.o pad.o regcomp.o dump.o util.o \
mg.o reentr.o mro.o hv.o av.o run.o pp_hot.o sv.o \
pp.o scope.o pp_ctl.o pp_sys.o doop.o doio.o regexec.o \
utf8.o taint.o deb.o universal.o globals.o perlio.o \
numeric.o mathoms.o locale.o pp_pack.o pp_sort.o \
miniperlmain.o opmini.o perlmini.o
pp.o: In function `Perl_pp_pow':
pp.c:(.text+0x2db9): undefined reference to `pow'
...
collect2: error: ld returned 1 exit status
makefile:348: recipe for target 'miniperl' failed
make: *** [miniperl] Error 1 Другой участник P5P порекомендовал установить и использовать Devel::PatchPerl в этой ситуации, сначала для определения версии perl в данном коммите, а затем для исправления исходного кода в этой точке, чтобы облегчить сборку.
$ perl -MDevel::PatchPerl -e \
'print Devel::PatchPerl->determine_version("/path/to/sourcecode"),
"\n";'
5.11.1
$ perl -MDevel::PatchPerl -e \
'Devel::PatchPerl->patch_source("5.11.1", "/path/to/sourcecode");' После того, как исходный код был исправлен, ./Configure и make test_prep были вызваны и успешно завершены, что позволило подтвердить результаты в RT #72414.
ДОПОЛНИТЕЛЬНОЕ ЧТЕНИЕ ДЛЯ ПРОГРАММИСТОВ-ЭНТУЗИАСТОВ
Чтобы работать над внутренностями Perl, вам нужно прочитать следующее:
-
Обзор дерева исходного кода Perl. Это поможет вам найти нужные файлы.
-
Обзор исходного кода интерпретатора Perl и некоторые подробности о том, как Perl делает то, что он делает.
-
Этот документ описывает создание небольшого патча для C-кода Perl. Если вы только начинаете работать с ядром Perl, это поможет вам понять, как это работает.
-
Более подробная информация о взломе ядра Perl. Этот документ фокусируется на деталях низкого уровня, таких как написание тестов, проблемы компиляции, переносимость, отладка и т.д.
Если вы планируете заниматься серьёзным взломом на C, обязательно прочитайте это.
-
Это имеет первостепенное значение, поскольку это документация о том, что где находится в исходном коде Perl. Прочитайте его пару раз, и он может начать иметь смысл - не беспокойтесь, если этого ещё не произошло, потому что лучший способ изучить его - это читать его в сочетании с изучением исходного кода Perl, и мы сделаем это позже.
«Иллюстрированный perlguts» Гисле Ааса, также известный как illguts, содержит очень полезные изображения:
-
Рабочее знание программирования XSUB невероятно полезно для взлома ядра; XSUB используют методы, взятые из кода PP, части внутренностей, которая фактически выполняет программу Perl. Гораздо проще изучить эти методы на простых примерах и объяснениях, чем на самом ядре.
-
Документация по API Perl объясняет, что делают некоторые внутренние функции, а также множество макросов, используемых в исходном коде.
-
Porting/pumpkin.pod
Это собрание мудрых слов для портера Perl; некоторые из них полезны только для владельцев pumpkin, но большая часть применима к любому, кто хочет заниматься разработкой Perl.
ТЕСТЕРЫ CPAN И КУРИЛЬЩИКИ PERL
Тестеры CPAN ( http://cpantesters.org/ ) - это группа добровольцев, которые тестируют модули CPAN на различных платформах.
Perl Smokers ( https://www.nntp.perl.org/group/perl.daily-build/ и https://www.nntp.perl.org/group/perl.daily-build.reports/ ) автоматически тестируют релизы исходного кода Perl на платформах с различными конфигурациями.
Оба проекта приветствуют добровольцев. Чтобы принять участие в дымовом тестировании самого perl, посетите https://metacpan.org/release/Test-Smoke. Чтобы начать дымовое тестирование модулей CPAN, посетите https://metacpan.org/release/CPANPLUS-YACSmoke или https://metacpan.org/release/minismokebox или https://metacpan.org/release/CPAN-Reporter.
ЧТО ДАЛЬШЕ?
Если вы прочитали всю документацию в этом документе и те, что указаны выше, вы более чем готовы взломать Perl.
Вот ещё несколько рекомендаций
-
Подпишитесь на perl5-porters, следите за патчами и попытайтесь понять их; не стесняйтесь спрашивать, если есть часть, которая вам не ясна - кто знает, вы можете обнаружить ошибку в патче...
-
Обязательно прочитайте README, связанный с вашей операционной системой, например, README.aix в ОС IBM AIX. Не стесняйтесь предоставлять патчи к этому README, если вы обнаружите что-либо отсутствующее или изменённое в новом релизе ОС.
-
Найдите область Perl, которая кажется вам интересной, и посмотрите, можете ли вы выяснить, как она работает. Просмотрите исходный код и пошагово пройдитесь по нему в отладчике. Играйте, копайте, исследуйте, возитесь! Вы, вероятно, поймёте не только выбранную вами область, но и гораздо более широкий спектр деятельности perl, и, вероятно, быстрее, чем вы думаете.
"Дорога вечно продолжается, вниз от двери, где она началась."
Если вы можете сделать это, вы начали долгий путь к портированию Perl. Спасибо за желание помочь сделать Perl лучше - и счастливого взлома!
Метафорические Цитаты
Если вы узнали цитату о Дороге выше, вам повезло.
Большинство программных проектов начинают каждый файл с буквального описания цели каждого файла. Perl вместо этого начинает каждый с литературной аллюзии на цель этого файла.
Как главы во многих книгах, все исходные файлы Perl верхнего уровня (наряду с несколькими другими здесь и там) начинаются с эпиграмматической надписи, которая косвенно и метафорически указывает на материал, который вы собираетесь прочитать.
Цитаты взяты из произведений Дж.Р.Р. Толкина, относящихся к его Легендариуму, почти всегда из Властелина Колец. Номера глав и страниц указаны с использованием следующих изданий:
-
Хоббит, Дж.Р.Р. Толкиен. Было использовано твердое издание к 70-летию 2007 года, опубликованное в Великобритании издательством Harper Collins Publishers и в США издательством Houghton Mifflin Company.
-
Властелин Колец, Дж.Р.Р. Толкиен. Было использовано твердое издание к 50-летию 2004 года, опубликованное в Великобритании издательством Harper Collins Publishers и в США издательством Houghton Mifflin Company.
-
Песни Белерианда, Дж.Р.Р. Толкиен, опубликовано посмертно его сыном и литературным душеприказчиком К.Дж.Р. Толкиеном, являясь 3-м из 12 томов в грандиозной Истории Средиземья Кристофера. Номера страниц взяты из твердого переплета, впервые опубликованного в 1983 году издательством George Allen & Unwin; номера страниц не изменились для специального 3-томного сборного издания 2002 года или различных изданий в мягкой обложке, все снова теперь от Harper Collins или Houghton Mifflin.
Другие книги Дж.Р.Р. Толкина, подходящие для цитат, включают Приключения Тома Бомбадила, Сильмариллион, Неоконченные сказания и История детей Хурина, все, кроме первой, собраны посмертно К.Дж.Р. Толкиеном. Но Властелин Колец сам по себе отлично подходит и, вероятно, лучше всего цитировать из него, при условии, что вы можете найти там подходящую цитату.
Поэтому, если бы вы предоставили новый, полный исходный файл верхнего уровня для добавления в Perl, вы должны были бы следовать этой своеобразной практике, самостоятельно выбрав подходящую цитату из Толкина, сохранив оригинальное написание и пунктуацию и используя тот же формат, что и остальные цитаты. Косвенность и непрямость вполне подходят; помните, это метафора, поэтому быть мета, в конце концов, именно для этого она предназначена.
АВТОР
Этот документ был первоначально написан Натаном Торкингтоном и поддерживается списком рассылки perl5-porters.
© 1993–2023 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.38.0/perlhack