Spec-Zone.ru › Perl 5.30

perlhack

СОДЕРЖАНИЕ

  • NAME
  • DESCRIPTION
  • SUPER QUICK PATCH GUIDE
  • BUG REPORTING
  • PERL 5 PORTERS
    • perl-changes mailing list
    • #p5p on IRC
  • GETTING THE PERL SOURCE
    • Read access via Git
    • Read access via the web
    • Read access via rsync
    • Write access via git
  • PATCHING PERL
    • Submitting patches
    • Getting your patch accepted
      • Patch style
      • Commit message
      • Comments, Comments, Comments
      • Style
      • Test suite
    • Patching a core module
    • Updating perldelta
    • What makes for a good patch?
      • Does the concept match the general goals of Perl?
      • Where is the implementation?
      • Backwards compatibility
      • Could it be a module instead?
      • Is the feature generic enough?
      • Does it potentially introduce new bugs?
      • How big is it?
      • Does it preclude other desirable features?
      • Is the implementation robust?
      • Is the implementation generic enough to be portable?
      • Is the implementation tested?
      • Is there enough documentation?
      • Is there another way to do it?
      • Does it create too much work?
      • Patches speak louder than words
  • TESTING
    • Special make test targets
    • Parallel tests
    • Running tests by hand
    • Using t/harness for testing
      • Other environment variables that may influence tests
    • Performance testing
    • Building perl at older commits
  • MORE READING FOR GUTS HACKERS
  • CPAN TESTERS AND PERL SMOKERS
  • WHAT NEXT?
    • "The Road goes ever on and on, down from the door where it began."
    • Metaphoric Quotations
  • AUTHOR

NAME

perlhack - Как взломать Perl

DESCRIPTION

В этом документе объясняется, как работает разработка Perl. Он включает в себя подробную информацию о списке рассылки Perl 5 Porters, репозитории Perl, системе отслеживания ошибок Perl, рекомендациях по патчам и комментариях к философии разработки Perl.

SUPER QUICK PATCH GUIDE

Если вы хотите отправить небольшой патч, например, исправление в подмодуле, тест для ошибки, исправления комментариев и т.д., это легко! Вот как:

  • Выполните checkout репозитория исходного кода

    Исходный код 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-форк репозитория perl5 и добавьте его как удалённый репозиторий, если вы ещё этого не сделали, как описано в документации GitHub по адресу https://help.github.com/en/articles/working-with-forks.

    % git remote add fork git@github.com:MyUser/perl5.git

    Затем отправьте вашу новую ветку в ваш форк.

    % git push -u fork mychange

    Наконец, создайте запрос на включение (Pull Request) на 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" или просто "разработчиками".

Поисковый архив списка доступен по адресу http://markmail.org/search/?q=perl5-porters. Существует также архив по адресу http://archive.develooper.com/perl5-porters@perl.org/.

Список рассылки perl-changes

Список рассылки perl5-changes получает копию каждого патча, который отправляется в ветки обслуживания и разработки репозитория Perl. См. http://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.

Доступ для чтения через rsync

Вы также можете использовать rsync для получения копии текущего дерева исходного кода для ветки bleadperl и всех веток обслуживания:

% rsync -avz rsync://perl5.git.perl.org/perl-current .
% rsync -avz rsync://perl5.git.perl.org/perl-5.12.x .
% rsync -avz rsync://perl5.git.perl.org/perl-5.10.x .
% rsync -avz rsync://perl5.git.perl.org/perl-5.8.x .
% rsync -avz rsync://perl5.git.perl.org/perl-5.6.x .
% rsync -avz rsync://perl5.git.perl.org/perl-5.005xx .

(Добавьте опцию --delete для удаления оставшихся файлов.)

Чтобы получить полный список доступных точек синхронизации:

% rsync perl5.git.perl.org::

Запись через 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 столбцов

  • Прототипы 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-default gcc, который выдает предупреждение всякий раз, когда оператор 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. Когда автор обновляет модуль, обновления просто копируются в ядро. См. документацию этого модуля или его список на http://search.cpan.org/ для получения дополнительной информации о сообщении об ошибках и отправке исправлений.

В большинстве случаев исправления модулей в cpan/ должны отправляться вверх по течению и не должны применяться к ядру Perl по отдельности. Если исправление файла в cpan/ абсолютно не может ждать, пока исправление будет внесено вверх по течению, выпущено в CPAN и скопировано в blead, вы должны добавить (или обновить) запись CUSTOMIZED в файл "Porting/Maintainers.pl", чтобы отметить, что было внесено локальное изменение. См. "Porting/Maintainers.pl" для получения более подробной информации.

В отличие от этого, модули в директории dist/ поддерживаются в ядре.

Обновление perldelta

Для изменений, достаточно значительных, чтобы гарантировать запись в pod/perldelta.pod, разработчики будут очень признательны, если вы отправите запись delta вместе с вашим фактическим изменением. К значительным изменениям относятся, но не ограничиваются ими:

  • Добавление, устаревание или удаление основных функций

  • Добавление, устаревание, удаление или обновление основных или dual-life модулей

  • Добавление новых основных тестов

  • Исправление проблем безопасности и видимых пользователями ошибок в ядре

  • Изменения, которые могут нарушить существующий код, как на уровне perl, так и на уровне C

  • Значительные улучшения производительности

  • Добавление, удаление или значительное изменение документации в директории pod/

  • Важные специфичные для платформы изменения

Пожалуйста, убедитесь, что вы добавили запись perldelta в правильный раздел в pod/perldelta.pod. Более подробная информация о том, как писать хорошие записи perldelta, доступна в разделе Style Porting/how_to_write_a_perldelta.pod.

Что делает патч хорошим?

Новые функции и расширения языка могут быть спорными. Нет конкретного набора критериев, определяющих, какие функции добавляются, но вот некоторые вопросы, которые следует учитывать при разработке патча:

Соответствует ли концепция общим целям Perl?

Наши цели включают, но не ограничиваются ими:

  1. Быстро, просто и полезно.

  2. Поддерживать функции/концепции максимально ортогональными.

  3. Отсутствие произвольных ограничений (платформы, размеры данных, культуры).

  4. Поддерживать его открытым и интересным для использования/патчинга/защиты Perl повсюду.

  5. Либо ассимилировать новые технологии, либо строить мосты к ним.

Где реализация?

Все разговоры в мире бесполезны без реализации. Почти в каждом случае ожидается, что человек или люди, выступающие за новую функцию, будут теми, кто ее реализует. Разработчики, способные кодировать новые функции, имеют свои собственные планы и не могут реализовать вашу (возможно, хорошую) идею.

Обратная совместимость

Нарушение существующих программ Perl — это тяжкий грех. Новые предупреждения могут быть спорными — некоторые говорят, что программа, которая выдает предупреждения, не сломана, а другие говорят, что сломана. Добавление ключевых слов может привести к поломке программ, изменение смысла существующих последовательностей токенов или функций может привести к поломке программ.

Ядро Perl 5 включает механизмы, которые помогают разработчикам сделать несовместимые с обратной совместимостью изменения более совместимыми, такие как модули feature и deprecate. Пожалуйста, используйте их, когда это уместно.

Может ли это быть модулем?

Perl 5 имеет механизмы расширения, модули и XS, специально для того, чтобы избежать необходимости постоянно изменять интерпретатор Perl. Вы можете написать модули, которые экспортируют функции, вы можете дать этим функциям прототипы, чтобы их можно было вызывать как встроенные функции, вы даже можете написать код XS, чтобы работать со структурами данных времени выполнения интерпретатора Perl, если вы хотите реализовать действительно сложные вещи.

Всякий раз, когда это возможно, новые функции должны быть созданы в виде прототипа в модуле CPAN, прежде чем они будут рассматриваться для ядра.

Достаточно ли универсальна функция?

Это то, что хочет добавить в язык только отправитель, или это широко полезно? Иногда, вместо добавления функции с узкой направленностью, разработчики могут решить подождать, пока кто-нибудь реализует более обобщенную функцию.

Может ли это привести к новым ошибкам?

Радикальная переработка больших фрагментов интерпретатора Perl может привести к появлению новых ошибок.

Насколько это большое изменение?

Чем меньше и более локализовано изменение, тем лучше. Аналогично, серия небольших патчей значительно предпочтительнее одного большого патча.

Препятствует ли это другим желаемым функциям?

Патч, скорее всего, будет отклонен, если он закроет будущие пути развития. Например, патч, который дал бы истинное и окончательное толкование прототипам, скорее всего, будет отклонен, потому что все еще есть варианты для будущего прототипов, которые не были рассмотрены.

Надежна ли реализация?

Хорошие патчи (компактный код, полный, корректный) имеют больше шансов быть принятыми. Небрежные или некорректные патчи могут быть отложены до тех пор, пока у разработчика не будет времени их исправить, или могут быть полностью отброшены без дальнейшего уведомления.

Достаточно ли универсальна реализация, чтобы быть переносимой?

Худшие патчи используют специфические для системы функции. Весьма маловероятно, что непереносимые дополнения к языку Perl будут приняты.

Протестирована ли реализация?

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

Без тестов, предоставленных исходным автором, как кто-либо другой, изменяющий perl в будущем, может быть уверен, что он невольно не нарушил поведение, реализованное патчем? И без тестов, как автор патча может быть уверен, что его/ее тяжелый труд, вложенный в патч, не будет случайно выброшен кем-то в будущем?

Достаточно ли документации?

Заплаты без документации, вероятно, плохо продуманы или неполны. Никакие функции не могут быть добавлены или изменены без документации, поэтому важно отправлять заплату для соответствующих документов pod, а также исходного кода.

Есть ли другой способ сделать это?

Ларри сказал: «Хотя слоган Perl — Есть более чем один способ сделать это, я колеблюсь, чтобы сделать 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/cmd, t/run, t/io и t/op

    Теперь, когда базовые require() и подпрограммы протестированы, вы можете использовать библиотеку t/test.pl.

    Вы также можете условно использовать определенные библиотеки, например Config, но обязательно корректно пропустите тест, если его нет.

  • Все остальное

    Теперь, когда ядро Perl протестировано, Test::More может и должен использоваться. Вы также можете использовать полный набор основных модулей в тестах.

Когда вы говорите «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' на всех платформах. Побочные эффекты:

  • Эти правила выбирают кодировку Юникод. Это означает, что в строках, заключенных в двойные кавычки, строка всегда преобразуется в UTF-8 для принудительного использования интерпретации Юникод (позже вы можете 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.

  • 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" нет.

    Под целью "test" в Win32 вы можете использовать переменные среды TEST_SWITCHES и TEST_FILES для управления поведением t/harness. Это означает, что вы можете сказать

    nmake test TEST_FILES="op/*.t"
    nmake test TEST_SWITCHES="-torture" TEST_FILES="op/*.t"
  • test-notty test_notty

    Устанавливает PERL_SKIP_TTY_TEST в true перед запуском обычного теста.

Параллельные тесты

Основное распространение теперь может запускать свои регрессионные тесты параллельно на платформах, подобных Unix. Вместо запуска make test, установите TEST_JOBS в своей среде на число тестов для параллельного запуска и запустите make test_harness. В оболочке типа Bourne это можно сделать так:

TEST_JOBS=3 make test_harness  # Run 3 tests in parallel

Используется переменная среды, а не сам параллельный make, потому что TAP::Harness должен иметь возможность сам планировать отдельные неконфликтующие тестовые сценарии, и нет стандартного интерфейса для взаимодействия с утилитами make для взаимодействия с их планировщиками заданий.

Обратите внимание, что в настоящее время некоторые тестовые сценарии могут завершиться неудачей при параллельном запуске (в первую очередь dist/IO/t/io_dir.t). При необходимости запустите снова только неудачные сценарии последовательно и посмотрите, исчезнут ли ошибки.

Запуск тестов вручную

Вы можете запустить часть набора тестов вручную, используя одну из следующих команд из каталога 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 СПИСОК ШАБЛОНОВ ниже тем, что позволяет также указать список файлов.

  • -re СПИСОК ШАБЛОНОВ

    Отфильтровать список файлов так, чтобы все запущенные тестовые файлы соответствовали /(LIST|OF|PATTERNS)/. Обратите внимание, что с этой формой шаблоны соединяются с помощью '|' и вы не можете указать список файлов, вместо этого тестовые файлы получаются из MANIFEST.

Вы можете запустить отдельный тест с помощью команды, подобной

./perl -I../lib path/to/foo.t

за исключением того, что программы подготовки устанавливают некоторые переменные среды, которые могут влиять на выполнение теста:

  • 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 #72414. Использование 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 \
  perlapi.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, вам нужно прочитать следующее:

  • perlsource

    Обзор дерева исходного кода Perl. Это поможет вам найти нужные файлы.

  • perlinterp

    Обзор исходного кода интерпретатора Perl и некоторые подробности о том, как Perl делает то, что он делает.

  • perlhacktut

    В этом документе описывается создание небольшого исправления для C-кода Perl. Если вы только начинаете работать с ядром Perl, это поможет вам понять, как это работает.

  • perlhacktips

    Более подробная информация о взломе ядра Perl. Этот документ фокусируется на деталях более низкого уровня, таких как написание тестов, проблемы компиляции, переносимость, отладка и т. д.

    Если вы планируете заниматься серьезным взломом C, обязательно прочитайте это.

  • perlguts

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

    «Иллюстрированный perlguts» Гисле Ааса, также известный как illguts, содержит очень полезные изображения:

    http://search.cpan.org/dist/illguts/

  • perlxstut и perlxs

    Рабочее знание программирования XSUB невероятно полезно для взлома ядра; XSUB используют методы, взятые из кода PP, части внутренностей, которая фактически выполняет программу Perl. Гораздо проще изучить эти методы из простых примеров и объяснений, чем из самого ядра.

  • perlapi

    В документации по API Perl объясняется, что делают некоторые внутренние функции, а также многие макросы, используемые в исходном коде.

  • Porting/pumpkin.pod

    Это собрание мудрых слов для портера Perl; некоторые из них полезны только для владельца тыквы, но большинство из них применимы к любому, кто хочет заниматься разработкой Perl.

CPAN TESTERS И ТЕСТЕРЫ PERL

Тестеры CPAN ( http://testers.cpan.org/ ) — это группа добровольцев, которые тестируют модули CPAN на различных платформах.

Perl Smokers ( http://www.nntp.perl.org/group/perl.daily-build/ и http://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, вы должны следовать этой своеобразной практике, самостоятельно выбрав подходящую цитату из Толкина, сохранив оригинальное написание и пунктуацию и используя тот же формат, в котором написаны остальные цитаты. Косвенное и непрямое подходит идеально; помните, это метафора, так что быть мета, в конце концов, именно то, для чего она предназначена.

AUTHOR

Этот документ был первоначально написан Натаном Торкингтоном и поддерживается списком рассылки perl5-porters.

© 1993–2020 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.30.3/perlhack

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API