Codebase list libparams-validate-perl / 07a7d8b
Imported Upstream version 1.23 Lucas Kanashiro 8 years ago
107 changed file(s) with 3876 addition(s) and 3576 deletion(s). Raw diff Collapse all Expand all
1919 "Ilya Martynov <ilya\@martynov.org>"
2020 ],
2121 "dist_name" => "Params-Validate",
22 "dist_version" => "1.22",
22 "dist_version" => "1.23",
2323 "license" => "artistic_2",
2424 "module_name" => "Params::Validate",
2525 "recursive_test_files" => 1,
2626 "requires" => {
2727 "Carp" => 0,
2828 "Exporter" => 0,
29 "JSON::PP" => "2.27300",
3029 "Module::Implementation" => 0,
3130 "Scalar::Util" => "1.10",
3231 "XSLoader" => 0,
0 # CONTRIBUTING
1
2 Thank you for considering contributing to this distribution. This file
3 contains instructions that will help you work with the source code.
4
5 Please note that if you have any questions or difficulties, you can reach the
6 maintainer(s) through the bug queue described later in this document
7 (preferred), or by emailing the releaser directly. You are not required to
8 follow any of the steps in this document to submit a patch or bug report;
9 these are just recommendations, intended to help you (and help us help you
10 faster).
11
12 This distribution has a TODO file in the repository; you may want to check
13 there to see if your issue or patch idea is mentioned.
14
15
16 The distribution is managed with
17 [Dist::Zilla](https://metacpan.org/release/Dist-Zilla).
18
19 However, you can still compile and test the code with the `Makefile.PL` in the
20 repository:
21
22 perl Makefile.PL
23 make
24 make test
25
26 As well as:
27
28 $ prove -bvr t
29
30 or
31
32 $ perl -Mblib t/some_test_file.t
33
34 You may need to satisfy some dependencies. The easiest way to satisfy
35 dependencies is to install the last release. This is available at
36 https://metacpan.org/release/Params-Validate
37
38 If you use cpanminus, you can do it without downloading the tarball first:
39
40 $ cpanm --reinstall --installdeps --with-recommends Params::Validate
41
42 Dist::Zilla is a very powerful authoring tool, but requires a number of
43 author-specific plugins. If you would like to use it for contributing, install
44 it from CPAN, then run one of the following commands, depending on your CPAN
45 client:
46
47 $ cpan `dzil authordeps --missing`
48
49 or
50
51 $ dzil authordeps --missing | cpanm
52
53 They may also be additional requirements not needed by the dzil build which
54 are needed for tests or other development:
55
56 $ cpan `dzil listdeps --author --missing`
57
58 or
59
60 $ dzil listdeps --author --missing | cpanm
61
62 Or, you can use the 'dzil stale' command to install all requirements at once:
63
64 $ cpan Dist::Zilla::App::Command::stale
65 $ cpan `dzil stale --all`
66
67 or
68
69 $ cpanm Dist::Zilla::App::Command::stale
70 $ dzil stale --all | cpanm
71
72 You can also do this via cpanm directly:
73
74 $ cpanm --reinstall --installdeps --with-develop --with-recommends Params::Validate
75
76 Once installed, here are some dzil commands you might try:
77
78 $ dzil build
79 $ dzil test
80 $ dzil test --release
81 $ dzil xtest
82 $ dzil listdeps --json
83 $ dzil build --notgz
84
85 You can learn more about Dist::Zilla at http://dzil.org/.
86
87 The code for this distribution is [hosted at GitHub](https://github.com/autarch/Params-Validate).
88
89 You can submit code changes by forking the repository, pushing your code
90 changes to your clone, and then submitting a pull request. Detailed
91 instructions for doing that is available here:
92
93 https://help.github.com/articles/creating-a-pull-request
94
95 If you have found a bug, but do not have an accompanying patch to fix it, you
96 can submit an issue report [via the web](http://rt.cpan.org/Public/Dist/Display.html?Name=Params-Validate)
97 or [via email](bug-params-validate@rt.cpan.org.
98 This is a good place to send your questions about the usage of this distribution.
99
100 ## Travis
101
102 All pull requests for this distribution will be automatically tested by
103 [Travis](https://travis-ci.org/) and the build status will be reported on the
104 pull request page. If your build fails, please take a look at the output.
105
106 ## Tidyall
107
108 This distribution uses
109 [Code::TidyAll](https://metacpan.org/release/Code-TidyAll) to enforce a
110 uniform coding style. This is tested as part of the author testing. You can
111 install and run tidyall by running the following commands:
112
113 $ cpanm Code::TidyAll
114 $ tidyall -a
115
116 Please run this before committing your changes and address any issues it
117 brings up.
118
119 ## Contributor Names
120
121 If you send me a patch or pull request, your name and email address will be
122 included in the documentation as a contributor (using the attribution on the
123 commit or patch), unless you specifically request for it not to be. If you
124 wish to be listed under a different name or address, you should submit a pull
125 request to the .mailmap file to contain the correct mapping.
126
127 This file was generated via Dist::Zilla::Plugin::GenerateFile::FromShareDir 0.009 from a
128 template file originating in Dist-Zilla-PluginBundle-DROLSKY-0.45.
0 1.23 2016-03-26
1
2 - Fixed some Perl stack corruption bugs. Based on a proposed PR from Tony Cook
3 plus some additional changes. GH #8.
4
5 - Fixed tests with Carp 1.01 (shipped with Perl 5.8.3). Patch by Andreas
6 Koenig. RT #113318.
7
8
09 1.22 2016-02-13
110
211 - Fixed a bug when a callback failed but did not die. The resulting error
00 # This file was automatically generated by Dist::Zilla::Plugin::Manifest v5.043.
11 Build.PL
2 CONTRIBUTING.md
23 Changes
34 INSTALL
45 LICENSE
6263 t/39-reentrant.t
6364 t/author-00-compile.t
6465 t/author-eol.t
66 t/author-memory-leak.t
6567 t/author-mojibake.t
6668 t/author-no-tabs.t
6769 t/author-pod-spell.t
6870 t/author-pod-syntax.t
71 t/author-pp-01-validate.t
72 t/author-pp-02-noop.t
73 t/author-pp-04-defaults.t
74 t/author-pp-05-noop_default.t
75 t/author-pp-06-options.t
76 t/author-pp-07-with.t
77 t/author-pp-08-noop_with.t
78 t/author-pp-09-regex.t
79 t/author-pp-10-noop_regex.t
80 t/author-pp-11-cb.t
81 t/author-pp-12-noop_cb.t
82 t/author-pp-13-taint.t
83 t/author-pp-14-no_validate.t
84 t/author-pp-15-case.t
85 t/author-pp-16-normalize.t
86 t/author-pp-17-callbacks.t
87 t/author-pp-18-depends.t
88 t/author-pp-19-untaint.t
89 t/author-pp-21-can.t
90 t/author-pp-22-overload-can-bug.t
91 t/author-pp-23-readonly.t
92 t/author-pp-24-tied.t
93 t/author-pp-25-undef-regex.t
94 t/author-pp-26-isa.t
95 t/author-pp-27-string-as-type.t
96 t/author-pp-28-readonly-return.t
97 t/author-pp-29-taint-mode.t
98 t/author-pp-30-hashref-alteration.t
99 t/author-pp-31-incorrect-spelling.t
100 t/author-pp-32-regex-as-value.t
101 t/author-pp-33-keep-errsv.t
102 t/author-pp-34-recursive-validation.t
103 t/author-pp-35-default-xs-bug.t
104 t/author-pp-36-large-arrays.t
105 t/author-pp-37-exports.t
106 t/author-pp-38-callback-message.t
107 t/author-pp-39-reentrant.t
108 t/author-pp-is-loaded.t
109 t/author-xs-is-loaded.t
110 t/author-xs-segfault.t
111 t/author-xs-stack-realloc.t
69112 t/lib/PVTests.pm
70113 t/lib/PVTests/Callbacks.pm
71114 t/lib/PVTests/Defaults.pm
73116 t/lib/PVTests/Standard.pm
74117 t/lib/PVTests/With.pm
75118 t/release-cpan-changes.t
76 t/release-memory-leak.t
77119 t/release-meta-json.t
78120 t/release-pod-coverage.t
79121 t/release-pod-linkcheck.t
80122 t/release-pod-no404s.t
81123 t/release-portability.t
82 t/release-pp-01-validate.t
83 t/release-pp-02-noop.t
84 t/release-pp-04-defaults.t
85 t/release-pp-05-noop_default.t
86 t/release-pp-06-options.t
87 t/release-pp-07-with.t
88 t/release-pp-08-noop_with.t
89 t/release-pp-09-regex.t
90 t/release-pp-10-noop_regex.t
91 t/release-pp-11-cb.t
92 t/release-pp-12-noop_cb.t
93 t/release-pp-13-taint.t
94 t/release-pp-14-no_validate.t
95 t/release-pp-15-case.t
96 t/release-pp-16-normalize.t
97 t/release-pp-17-callbacks.t
98 t/release-pp-18-depends.t
99 t/release-pp-19-untaint.t
100 t/release-pp-21-can.t
101 t/release-pp-22-overload-can-bug.t
102 t/release-pp-23-readonly.t
103 t/release-pp-24-tied.t
104 t/release-pp-25-undef-regex.t
105 t/release-pp-26-isa.t
106 t/release-pp-27-string-as-type.t
107 t/release-pp-28-readonly-return.t
108 t/release-pp-29-taint-mode.t
109 t/release-pp-30-hashref-alteration.t
110 t/release-pp-31-incorrect-spelling.t
111 t/release-pp-32-regex-as-value.t
112 t/release-pp-33-keep-errsv.t
113 t/release-pp-34-recursive-validation.t
114 t/release-pp-35-default-xs-bug.t
115 t/release-pp-36-large-arrays.t
116 t/release-pp-37-exports.t
117 t/release-pp-38-callback-message.t
118 t/release-pp-39-reentrant.t
119 t/release-pp-is-loaded.t
120124 t/release-synopsis.t
121 t/release-xs-is-loaded.t
122 t/release-xs-segfault.t
123 t/release-xs-stack-realloc.t
124125 tidyall.ini
125126 weaver.ini
2222 "configure" : {
2323 "requires" : {
2424 "Module::Build" : "0.28"
25 },
26 "suggests" : {
27 "JSON::PP" : "2.27300"
2528 }
2629 },
2730 "develop" : {
5457 "requires" : {
5558 "Carp" : "0",
5659 "Exporter" : "0",
57 "JSON::PP" : "2.27300",
5860 "Module::Implementation" : "0",
5961 "Scalar::Util" : "1.10",
6062 "XSLoader" : "0",
8789 "provides" : {
8890 "Params::Validate" : {
8991 "file" : "lib/Params/Validate.pm",
90 "version" : "1.22"
92 "version" : "1.23"
9193 },
9294 "Params::Validate::Constants" : {
9395 "file" : "lib/Params/Validate/Constants.pm",
94 "version" : "1.22"
96 "version" : "1.23"
9597 },
9698 "Params::Validate::PP" : {
9799 "file" : "lib/Params/Validate/PP.pm",
98 "version" : "1.22"
100 "version" : "1.23"
99101 },
100102 "Params::Validate::XS" : {
101103 "file" : "lib/Params/Validate/XS.pm",
102 "version" : "1.22"
104 "version" : "1.23"
103105 }
104106 },
105107 "release_status" : "stable",
115117 "web" : "https://github.com/autarch/Params-Validate"
116118 }
117119 },
118 "version" : "1.22",
120 "version" : "1.23",
119121 "x_Dist_Zilla" : {
120122 "perl" : {
121123 "version" : "5.022001"
142144 "Dist::Zilla::Plugin::GatherDir" : {
143145 "exclude_filename" : [
144146 "Build.PL",
147 "CONTRIBUTING.md",
145148 "LICENSE",
146149 "Makefile.PL",
147150 "README.md",
148 "cpanfile"
151 "cpanfile",
152 "ppport.h"
149153 ],
150154 "exclude_match" : [],
151155 "follow_symlinks" : 0,
238242 "modules" : [],
239243 "phase" : "release",
240244 "skip" : [
245 "Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent",
241246 "Dist::Zilla::Plugin::DROLSKY::Contributors",
247 "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch",
242248 "Dist::Zilla::Plugin::DROLSKY::License",
243249 "Dist::Zilla::Plugin::DROLSKY::TidyAll",
244250 "Dist::Zilla::Plugin::DROLSKY::VersionProvider"
247253 },
248254 "name" : "@DROLSKY/PromptIfStale",
249255 "version" : "0.047"
250 },
251 {
252 "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
253 "config" : {
254 "Dist::Zilla::Role::FileWatcher" : {
255 "version" : "0.006"
256 }
257 },
258 "name" : "@DROLSKY/README.md in build",
259 "version" : "0.150250"
260 },
261 {
262 "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
263 "config" : {
264 "Dist::Zilla::Role::FileWatcher" : {
265 "version" : "0.006"
266 }
267 },
268 "name" : "@DROLSKY/README.md in root",
269 "version" : "0.150250"
270256 },
271257 {
272258 "class" : "Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable",
293279 "SCALARREF",
294280 "ValidatePos",
295281 "baz",
282 "drolsky",
296283 "onwards",
297284 "pre",
298285 "runtime"
306293 {
307294 "class" : "Dist::Zilla::Plugin::Test::ReportPrereqs",
308295 "name" : "@DROLSKY/Test::ReportPrereqs",
309 "version" : "0.021"
296 "version" : "0.024"
310297 },
311298 {
312299 "class" : "Dist::Zilla::Plugin::ManifestSkip",
364351 "version" : "5.043"
365352 },
366353 {
354 "class" : "Dist::Zilla::Plugin::GenerateFile::FromShareDir",
355 "config" : {
356 "Dist::Zilla::Plugin::GenerateFile::FromShareDir" : {
357 "destination_filename" : "CONTRIBUTING.md",
358 "dist" : "Dist-Zilla-PluginBundle-DROLSKY",
359 "encoding" : "UTF-8",
360 "has_xs" : "",
361 "location" : "build",
362 "source_filename" : "CONTRIBUTING.md"
363 },
364 "Dist::Zilla::Role::RepoFileInjector" : {
365 "allow_overwrite" : 1,
366 "repo_root" : ".",
367 "version" : "0.005"
368 }
369 },
370 "name" : "@DROLSKY/generate CONTRIBUTING",
371 "version" : "0.009"
372 },
373 {
367374 "class" : "Dist::Zilla::Plugin::CheckPrereqsIndexed",
368375 "name" : "@DROLSKY/CheckPrereqsIndexed",
369376 "version" : "0.017"
374381 "version" : "5.043"
375382 },
376383 {
384 "class" : "Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent",
385 "name" : "@DROLSKY/DROLSKY::CheckChangesHasContent",
386 "version" : "0.45"
387 },
388 {
377389 "class" : "Dist::Zilla::Plugin::DROLSKY::Contributors",
378390 "name" : "@DROLSKY/DROLSKY::Contributors",
379 "version" : "0.42"
391 "version" : "0.45"
380392 },
381393 {
382394 "class" : "Dist::Zilla::Plugin::DROLSKY::License",
383395 "name" : "@DROLSKY/DROLSKY::License",
384 "version" : "0.42"
396 "version" : "0.45"
385397 },
386398 {
387399 "class" : "Dist::Zilla::Plugin::DROLSKY::TidyAll",
388400 "name" : "@DROLSKY/DROLSKY::TidyAll",
389 "version" : "0.42"
401 "version" : "0.45"
390402 },
391403 {
392404 "class" : "Dist::Zilla::Plugin::DROLSKY::VersionProvider",
393405 "name" : "@DROLSKY/DROLSKY::VersionProvider",
394 "version" : "0.42"
406 "version" : "0.45"
395407 },
396408 {
397409 "class" : "Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch",
401413 }
402414 },
403415 "name" : "@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch",
404 "version" : "0.42"
416 "version" : "0.45"
405417 },
406418 {
407419 "class" : "Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts",
426438 }
427439 },
428440 "name" : "@DROLSKY/Git::Contributors",
429 "version" : "0.018"
441 "version" : "0.020"
430442 },
431443 {
432444 "class" : "Dist::Zilla::Plugin::InstallGuide",
436448 {
437449 "class" : "Dist::Zilla::Plugin::Meta::Contributors",
438450 "name" : "@DROLSKY/Meta::Contributors",
439 "version" : "0.002"
451 "version" : "0.003"
440452 },
441453 {
442454 "class" : "Dist::Zilla::Plugin::MetaConfig",
452464 "class" : "Dist::Zilla::Plugin::SurgicalPodWeaver",
453465 "config" : {
454466 "Dist::Zilla::Plugin::PodWeaver" : {
467 "config_plugins" : [
468 "@DROLSKY"
469 ],
455470 "finder" : [
456471 ":InstallModules",
457472 ":ExecFiles"
468483 "version" : "4.012"
469484 },
470485 {
486 "class" : "Pod::Weaver::Plugin::SingleEncoding",
487 "name" : "@DROLSKY/SingleEncoding",
488 "version" : "4.012"
489 },
490 {
491 "class" : "Pod::Weaver::Plugin::Transformer",
492 "name" : "@DROLSKY/List",
493 "version" : "4.012"
494 },
495 {
496 "class" : "Pod::Weaver::Plugin::Transformer",
497 "name" : "@DROLSKY/Verbatim",
498 "version" : "4.012"
499 },
500 {
501 "class" : "Pod::Weaver::Section::Region",
502 "name" : "@DROLSKY/header",
503 "version" : "4.012"
504 },
505 {
471506 "class" : "Pod::Weaver::Section::Name",
472 "name" : "Name",
507 "name" : "@DROLSKY/Name",
473508 "version" : "4.012"
474509 },
475510 {
476511 "class" : "Pod::Weaver::Section::Version",
477 "name" : "Version",
512 "name" : "@DROLSKY/Version",
478513 "version" : "4.012"
479514 },
480515 {
481516 "class" : "Pod::Weaver::Section::Region",
482 "name" : "prelude",
517 "name" : "@DROLSKY/prelude",
483518 "version" : "4.012"
484519 },
485520 {
493528 "version" : "4.012"
494529 },
495530 {
531 "class" : "Pod::Weaver::Section::Generic",
532 "name" : "OVERVIEW",
533 "version" : "4.012"
534 },
535 {
536 "class" : "Pod::Weaver::Section::Collect",
537 "name" : "ATTRIBUTES",
538 "version" : "4.012"
539 },
540 {
541 "class" : "Pod::Weaver::Section::Collect",
542 "name" : "METHODS",
543 "version" : "4.012"
544 },
545 {
546 "class" : "Pod::Weaver::Section::Collect",
547 "name" : "FUNCTIONS",
548 "version" : "4.012"
549 },
550 {
551 "class" : "Pod::Weaver::Section::Collect",
552 "name" : "TYPES",
553 "version" : "4.012"
554 },
555 {
496556 "class" : "Pod::Weaver::Section::Leftovers",
497 "name" : "Leftovers",
557 "name" : "@DROLSKY/Leftovers",
498558 "version" : "4.012"
499559 },
500560 {
501561 "class" : "Pod::Weaver::Section::Region",
502 "name" : "postlude",
503 "version" : "4.012"
562 "name" : "@DROLSKY/postlude",
563 "version" : "4.012"
564 },
565 {
566 "class" : "Pod::Weaver::Section::GenerateSection",
567 "name" : "@DROLSKY/generate SUPPORT",
568 "version" : "1.01"
569 },
570 {
571 "class" : "Pod::Weaver::Section::AllowOverride",
572 "name" : "@DROLSKY/allow override SUPPORT",
573 "version" : "0.05"
574 },
575 {
576 "class" : "Pod::Weaver::Section::GenerateSection",
577 "name" : "@DROLSKY/generate DONATIONS",
578 "version" : "1.01"
504579 },
505580 {
506581 "class" : "Pod::Weaver::Section::Authors",
507 "name" : "Authors",
582 "name" : "@DROLSKY/Authors",
508583 "version" : "4.012"
509584 },
510585 {
511586 "class" : "Pod::Weaver::Section::Contributors",
512 "name" : "Contributors",
587 "name" : "@DROLSKY/Contributors",
513588 "version" : "0.009"
514589 },
515590 {
516591 "class" : "Pod::Weaver::Section::Legal",
517 "name" : "Legal",
592 "name" : "@DROLSKY/Legal",
593 "version" : "4.012"
594 },
595 {
596 "class" : "Pod::Weaver::Section::Region",
597 "name" : "@DROLSKY/footer",
518598 "version" : "4.012"
519599 }
520600 ]
522602 },
523603 "name" : "@DROLSKY/SurgicalPodWeaver",
524604 "version" : "0.0023"
605 },
606 {
607 "class" : "Dist::Zilla::Plugin::ReadmeAnyFromPod",
608 "config" : {
609 "Dist::Zilla::Role::FileWatcher" : {
610 "version" : "0.006"
611 }
612 },
613 "name" : "@DROLSKY/README.md in build",
614 "version" : "0.160630"
525615 },
526616 {
527617 "class" : "Dist::Zilla::Plugin::MojibakeTests",
620710 "LICENSE",
621711 "Makefile.PL",
622712 "README.md",
623 "cpanfile"
713 "cpanfile",
714 "ppport.h"
624715 ],
625716 "allow_dirty_match" : [],
626717 "changelog" : "Changes"
647738 "LICENSE",
648739 "Makefile.PL",
649740 "README.md",
650 "cpanfile"
741 "cpanfile",
742 "ppport.h"
651743 ],
652744 "allow_dirty_match" : [],
653745 "changelog" : "Changes"
669761 "branch" : null,
670762 "changelog" : "Changes",
671763 "signed" : 0,
672 "tag" : "v1.22",
764 "tag" : "v1.23",
673765 "tag_format" : "v%v",
674766 "tag_message" : "v%v"
675767 },
712804 }
713805 },
714806 "name" : "@DROLSKY/BumpVersionAfterRelease",
715 "version" : "0.013"
807 "version" : "0.015"
716808 },
717809 {
718810 "class" : "Dist::Zilla::Plugin::Git::Commit",
791883 {
792884 "class" : "Dist::Zilla::Plugin::PurePerlTests",
793885 "name" : "PurePerlTests",
794 "version" : "0.05"
886 "version" : "0.06"
795887 },
796888 {
797889 "class" : "Dist::Zilla::Plugin::FinderCode",
863955 "J.R. Mash <jmash.code@gmail.com>",
864956 "Noel Maddy <zhtwnpanta@gmail.com>",
865957 "Olivier Mengué <dolmen@cpan.org>",
958 "Tony Cook <tony@develop-help.com>",
866959 "Vincent Pit <perl@profvince.com>"
867960 ]
868961 }
2828 provides:
2929 Params::Validate:
3030 file: lib/Params/Validate.pm
31 version: '1.22'
31 version: '1.23'
3232 Params::Validate::Constants:
3333 file: lib/Params/Validate/Constants.pm
34 version: '1.22'
34 version: '1.23'
3535 Params::Validate::PP:
3636 file: lib/Params/Validate/PP.pm
37 version: '1.22'
37 version: '1.23'
3838 Params::Validate::XS:
3939 file: lib/Params/Validate/XS.pm
40 version: '1.22'
40 version: '1.23'
4141 requires:
4242 Carp: '0'
4343 Exporter: '0'
44 JSON::PP: '2.27300'
4544 Module::Implementation: '0'
4645 Scalar::Util: '1.10'
4746 XSLoader: '0'
5352 bugtracker: http://rt.cpan.org/Public/Dist/Display.html?Name=Params-Validate
5453 homepage: http://metacpan.org/release/Params-Validate
5554 repository: git://github.com/autarch/Params-Validate.git
56 version: '1.22'
55 version: '1.23'
5756 x_Dist_Zilla:
5857 perl:
5958 version: '5.022001'
7675 Dist::Zilla::Plugin::GatherDir:
7776 exclude_filename:
7877 - Build.PL
78 - CONTRIBUTING.md
7979 - LICENSE
8080 - Makefile.PL
8181 - README.md
8282 - cpanfile
83 - ppport.h
8384 exclude_match: []
8485 follow_symlinks: 0
8586 include_dotfiles: 0
149150 modules: []
150151 phase: release
151152 skip:
153 - Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent
152154 - Dist::Zilla::Plugin::DROLSKY::Contributors
155 - Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch
153156 - Dist::Zilla::Plugin::DROLSKY::License
154157 - Dist::Zilla::Plugin::DROLSKY::TidyAll
155158 - Dist::Zilla::Plugin::DROLSKY::VersionProvider
156159 name: '@DROLSKY/PromptIfStale'
157160 version: '0.047'
158 -
159 class: Dist::Zilla::Plugin::ReadmeAnyFromPod
160 config:
161 Dist::Zilla::Role::FileWatcher:
162 version: '0.006'
163 name: '@DROLSKY/README.md in build'
164 version: '0.150250'
165 -
166 class: Dist::Zilla::Plugin::ReadmeAnyFromPod
167 config:
168 Dist::Zilla::Role::FileWatcher:
169 version: '0.006'
170 name: '@DROLSKY/README.md in root'
171 version: '0.150250'
172161 -
173162 class: Dist::Zilla::Plugin::Test::Pod::Coverage::Configurable
174163 name: '@DROLSKY/Test::Pod::Coverage::Configurable'
193182 - SCALARREF
194183 - ValidatePos
195184 - baz
185 - drolsky
196186 - onwards
197187 - pre
198188 - runtime
202192 -
203193 class: Dist::Zilla::Plugin::Test::ReportPrereqs
204194 name: '@DROLSKY/Test::ReportPrereqs'
205 version: '0.021'
195 version: '0.024'
206196 -
207197 class: Dist::Zilla::Plugin::ManifestSkip
208198 name: '@DROLSKY/ManifestSkip'
248238 name: '@DROLSKY/UploadToCPAN'
249239 version: '5.043'
250240 -
241 class: Dist::Zilla::Plugin::GenerateFile::FromShareDir
242 config:
243 Dist::Zilla::Plugin::GenerateFile::FromShareDir:
244 destination_filename: CONTRIBUTING.md
245 dist: Dist-Zilla-PluginBundle-DROLSKY
246 encoding: UTF-8
247 has_xs: ''
248 location: build
249 source_filename: CONTRIBUTING.md
250 Dist::Zilla::Role::RepoFileInjector:
251 allow_overwrite: 1
252 repo_root: .
253 version: '0.005'
254 name: '@DROLSKY/generate CONTRIBUTING'
255 version: '0.009'
256 -
251257 class: Dist::Zilla::Plugin::CheckPrereqsIndexed
252258 name: '@DROLSKY/CheckPrereqsIndexed'
253259 version: '0.017'
256262 name: '@DROLSKY/CPANFile'
257263 version: '5.043'
258264 -
265 class: Dist::Zilla::Plugin::DROLSKY::CheckChangesHasContent
266 name: '@DROLSKY/DROLSKY::CheckChangesHasContent'
267 version: '0.45'
268 -
259269 class: Dist::Zilla::Plugin::DROLSKY::Contributors
260270 name: '@DROLSKY/DROLSKY::Contributors'
261 version: '0.42'
271 version: '0.45'
262272 -
263273 class: Dist::Zilla::Plugin::DROLSKY::License
264274 name: '@DROLSKY/DROLSKY::License'
265 version: '0.42'
275 version: '0.45'
266276 -
267277 class: Dist::Zilla::Plugin::DROLSKY::TidyAll
268278 name: '@DROLSKY/DROLSKY::TidyAll'
269 version: '0.42'
279 version: '0.45'
270280 -
271281 class: Dist::Zilla::Plugin::DROLSKY::VersionProvider
272282 name: '@DROLSKY/DROLSKY::VersionProvider'
273 version: '0.42'
283 version: '0.45'
274284 -
275285 class: Dist::Zilla::Plugin::DROLSKY::Git::CheckFor::CorrectBranch
276286 config:
277287 Dist::Zilla::Role::Git::Repo:
278288 repo_root: .
279289 name: '@DROLSKY/DROLSKY::Git::CheckFor::CorrectBranch'
280 version: '0.42'
290 version: '0.45'
281291 -
282292 class: Dist::Zilla::Plugin::Git::CheckFor::MergeConflicts
283293 config:
295305 paths:
296306 - .
297307 name: '@DROLSKY/Git::Contributors'
298 version: '0.018'
308 version: '0.020'
299309 -
300310 class: Dist::Zilla::Plugin::InstallGuide
301311 name: '@DROLSKY/InstallGuide'
303313 -
304314 class: Dist::Zilla::Plugin::Meta::Contributors
305315 name: '@DROLSKY/Meta::Contributors'
306 version: '0.002'
316 version: '0.003'
307317 -
308318 class: Dist::Zilla::Plugin::MetaConfig
309319 name: '@DROLSKY/MetaConfig'
316326 class: Dist::Zilla::Plugin::SurgicalPodWeaver
317327 config:
318328 Dist::Zilla::Plugin::PodWeaver:
329 config_plugins:
330 - '@DROLSKY'
319331 finder:
320332 - ':InstallModules'
321333 - ':ExecFiles'
329341 name: '@CorePrep/H1Nester'
330342 version: '4.012'
331343 -
344 class: Pod::Weaver::Plugin::SingleEncoding
345 name: '@DROLSKY/SingleEncoding'
346 version: '4.012'
347 -
348 class: Pod::Weaver::Plugin::Transformer
349 name: '@DROLSKY/List'
350 version: '4.012'
351 -
352 class: Pod::Weaver::Plugin::Transformer
353 name: '@DROLSKY/Verbatim'
354 version: '4.012'
355 -
356 class: Pod::Weaver::Section::Region
357 name: '@DROLSKY/header'
358 version: '4.012'
359 -
332360 class: Pod::Weaver::Section::Name
333 name: Name
361 name: '@DROLSKY/Name'
334362 version: '4.012'
335363 -
336364 class: Pod::Weaver::Section::Version
337 name: Version
365 name: '@DROLSKY/Version'
338366 version: '4.012'
339367 -
340368 class: Pod::Weaver::Section::Region
341 name: prelude
369 name: '@DROLSKY/prelude'
342370 version: '4.012'
343371 -
344372 class: Pod::Weaver::Section::Generic
349377 name: DESCRIPTION
350378 version: '4.012'
351379 -
380 class: Pod::Weaver::Section::Generic
381 name: OVERVIEW
382 version: '4.012'
383 -
384 class: Pod::Weaver::Section::Collect
385 name: ATTRIBUTES
386 version: '4.012'
387 -
388 class: Pod::Weaver::Section::Collect
389 name: METHODS
390 version: '4.012'
391 -
392 class: Pod::Weaver::Section::Collect
393 name: FUNCTIONS
394 version: '4.012'
395 -
396 class: Pod::Weaver::Section::Collect
397 name: TYPES
398 version: '4.012'
399 -
352400 class: Pod::Weaver::Section::Leftovers
353 name: Leftovers
401 name: '@DROLSKY/Leftovers'
354402 version: '4.012'
355403 -
356404 class: Pod::Weaver::Section::Region
357 name: postlude
358 version: '4.012'
405 name: '@DROLSKY/postlude'
406 version: '4.012'
407 -
408 class: Pod::Weaver::Section::GenerateSection
409 name: '@DROLSKY/generate SUPPORT'
410 version: '1.01'
411 -
412 class: Pod::Weaver::Section::AllowOverride
413 name: '@DROLSKY/allow override SUPPORT'
414 version: '0.05'
415 -
416 class: Pod::Weaver::Section::GenerateSection
417 name: '@DROLSKY/generate DONATIONS'
418 version: '1.01'
359419 -
360420 class: Pod::Weaver::Section::Authors
361 name: Authors
421 name: '@DROLSKY/Authors'
362422 version: '4.012'
363423 -
364424 class: Pod::Weaver::Section::Contributors
365 name: Contributors
425 name: '@DROLSKY/Contributors'
366426 version: '0.009'
367427 -
368428 class: Pod::Weaver::Section::Legal
369 name: Legal
429 name: '@DROLSKY/Legal'
430 version: '4.012'
431 -
432 class: Pod::Weaver::Section::Region
433 name: '@DROLSKY/footer'
370434 version: '4.012'
371435 name: '@DROLSKY/SurgicalPodWeaver'
372436 version: '0.0023'
437 -
438 class: Dist::Zilla::Plugin::ReadmeAnyFromPod
439 config:
440 Dist::Zilla::Role::FileWatcher:
441 version: '0.006'
442 name: '@DROLSKY/README.md in build'
443 version: '0.160630'
373444 -
374445 class: Dist::Zilla::Plugin::MojibakeTests
375446 name: '@DROLSKY/MojibakeTests'
448519 - Makefile.PL
449520 - README.md
450521 - cpanfile
522 - ppport.h
451523 allow_dirty_match: []
452524 changelog: Changes
453525 Dist::Zilla::Role::Git::Repo:
469541 - Makefile.PL
470542 - README.md
471543 - cpanfile
544 - ppport.h
472545 allow_dirty_match: []
473546 changelog: Changes
474547 Dist::Zilla::Role::Git::Repo:
484557 branch: ~
485558 changelog: Changes
486559 signed: 0
487 tag: v1.22
560 tag: v1.23
488561 tag_format: v%v
489562 tag_message: v%v
490563 Dist::Zilla::Role::Git::Repo:
514587 global: 0
515588 munge_makefile_pl: 1
516589 name: '@DROLSKY/BumpVersionAfterRelease'
517 version: '0.013'
590 version: '0.015'
518591 -
519592 class: Dist::Zilla::Plugin::Git::Commit
520593 config:
571644 -
572645 class: Dist::Zilla::Plugin::PurePerlTests
573646 name: PurePerlTests
574 version: '0.05'
647 version: '0.06'
575648 -
576649 class: Dist::Zilla::Plugin::FinderCode
577650 name: ':InstallModules'
627700 - 'J.R. Mash <jmash.code@gmail.com>'
628701 - 'Noel Maddy <zhtwnpanta@gmail.com>'
629702 - 'Olivier Mengué <dolmen@cpan.org>'
703 - 'Tony Cook <tony@develop-help.com>'
630704 - 'Vincent Pit <perl@profvince.com>'
0 NAME
1
2 Params::Validate - Validate method/function parameters
3
4 VERSION
5
6 version 1.22
7
8 SYNOPSIS
9
10 use Params::Validate qw(:all);
11
12 # takes named params (hash or hashref)
13 sub foo {
14 validate(
15 @_, {
16 foo => 1, # mandatory
17 bar => 0, # optional
18 }
19 );
20 }
21
22 # takes positional params
23 sub bar {
24 # first two are mandatory, third is optional
25 validate_pos( @_, 1, 1, 0 );
26 }
27
28 sub foo2 {
29 validate(
30 @_, {
31 foo =>
32 # specify a type
33 { type => ARRAYREF },
34 bar =>
35 # specify an interface
36 { can => [ 'print', 'flush', 'frobnicate' ] },
37 baz => {
38 type => SCALAR, # a scalar ...
39 # ... that is a plain integer ...
40 regex => qr/^\d+$/,
41 callbacks => { # ... and smaller than 90
42 'less than 90' => sub { shift() < 90 },
43 },
44 }
45 }
46 );
47 }
48
49 sub callback_with_custom_error {
50 validate(
51 @_,
52 {
53 foo => callbacks => {
54 'is an integer' => sub {
55 return 1 if $_[0] =~ /^-?[1-9][0-9]*$/;
56 die "$_[0] is not a valid integer value";
57 },
58 }
59 }
60 );
61 }
62
63 sub with_defaults {
64 my %p = validate(
65 @_, {
66 # required
67 foo => 1,
68 # $p{bar} will be 99 if bar is not given. bar is now
69 # optional.
70 bar => { default => 99 }
71 }
72 );
73 }
74
75 sub pos_with_defaults {
76 my @p = validate_pos( @_, 1, { default => 99 } );
77 }
78
79 sub sets_options_on_call {
80 my %p = validate_with(
81 params => \@_,
82 spec => { foo => { type => SCALAR, default => 2 } },
83 normalize_keys => sub { $_[0] =~ s/^-//; lc $_[0] },
84 );
85 }
86
87 DESCRIPTION
88
89 The Params::Validate module allows you to validate method or function
90 call parameters to an arbitrary level of specificity. At the simplest
91 level, it is capable of validating the required parameters were given
92 and that no unspecified additional parameters were passed in.
93
94 It is also capable of determining that a parameter is of a specific
95 type, that it is an object of a certain class hierarchy, that it
96 possesses certain methods, or applying validation callbacks to
97 arguments.
98
99 EXPORT
100
101 The module always exports the validate() and validate_pos() functions.
102
103 It also has an additional function available for export, validate_with,
104 which can be used to validate any type of parameters, and set various
105 options on a per-invocation basis.
106
107 In addition, it can export the following constants, which are used as
108 part of the type checking. These are SCALAR, ARRAYREF, HASHREF,
109 CODEREF, GLOB, GLOBREF, and SCALARREF, UNDEF, OBJECT, BOOLEAN, and
110 HANDLE. These are explained in the section on Type Validation.
111
112 The constants are available via the export tag :types. There is also an
113 :all tag which includes all of the constants as well as the
114 validation_options() function.
115
116 PARAMETER VALIDATION
117
118 The validation mechanisms provided by this module can handle both named
119 or positional parameters. For the most part, the same features are
120 available for each. The biggest difference is the way that the
121 validation specification is given to the relevant subroutine. The other
122 difference is in the error messages produced when validation checks
123 fail.
124
125 When handling named parameters, the module will accept either a hash or
126 a hash reference.
127
128 Subroutines expecting named parameters should call the validate()
129 subroutine like this:
130
0 # NAME
1
2 Params::Validate - Validate method/function parameters
3
4 # VERSION
5
6 version 1.23
7
8 # SYNOPSIS
9
10 use Params::Validate qw(:all);
11
12 # takes named params (hash or hashref)
13 sub foo {
13114 validate(
13215 @_, {
133 parameter1 => validation spec,
134 parameter2 => validation spec,
135 ...
16 foo => 1, # mandatory
17 bar => 0, # optional
13618 }
13719 );
138
139 Subroutines expecting positional parameters should call the
140 validate_pos() subroutine like this:
141
142 validate_pos( @_, { validation spec }, { validation spec } );
143
144 Mandatory/Optional Parameters
145
146 If you just want to specify that some parameters are mandatory and
147 others are optional, this can be done very simply.
148
149 For a subroutine expecting named parameters, you would do this:
150
151 validate( @_, { foo => 1, bar => 1, baz => 0 } );
152
153 This says that the "foo" and "bar" parameters are mandatory and that
154 the "baz" parameter is optional. The presence of any other parameters
155 will cause an error.
156
157 For a subroutine expecting positional parameters, you would do this:
158
159 validate_pos( @_, 1, 1, 0, 0 );
160
161 This says that you expect at least 2 and no more than 4 parameters. If
162 you have a subroutine that has a minimum number of parameters but can
163 take any maximum number, you can do this:
164
165 validate_pos( @_, 1, 1, (0) x (@_ - 2) );
166
167 This will always be valid as long as at least two parameters are given.
168 A similar construct could be used for the more complex validation
169 parameters described further on.
170
171 Please note that this:
172
173 validate_pos( @_, 1, 1, 0, 1, 1 );
174
175 makes absolutely no sense, so don't do it. Any zeros must come at the
176 end of the validation specification.
177
178 In addition, if you specify that a parameter can have a default, then
179 it is considered optional.
180
181 Type Validation
182
183 This module supports the following simple types, which can be exported
184 as constants:
185
186 * SCALAR
187
188 A scalar which is not a reference, such as 10 or 'hello'. A parameter
189 that is undefined is not treated as a scalar. If you want to allow
190 undefined values, you will have to specify SCALAR | UNDEF.
191
192 * ARRAYREF
193
194 An array reference such as [1, 2, 3] or \@foo.
195
196 * HASHREF
197
198 A hash reference such as { a => 1, b => 2 } or \%bar.
199
200 * CODEREF
201
202 A subroutine reference such as \&foo_sub or sub { print "hello" }.
203
204 * GLOB
205
206 This one is a bit tricky. A glob would be something like *FOO, but
207 not \*FOO, which is a glob reference. It should be noted that this
208 trick:
209
210 my $fh = do { local *FH; };
211
212 makes $fh a glob, not a glob reference. On the other hand, the return
213 value from Symbol::gensym is a glob reference. Either can be used as
214 a file or directory handle.
215
216 * GLOBREF
217
218 A glob reference such as \*FOO. See the GLOB entry above for more
219 details.
220
221 * SCALARREF
222
223 A reference to a scalar such as \$x.
224
225 * UNDEF
226
227 An undefined value
228
229 * OBJECT
230
231 A blessed reference.
232
233 * BOOLEAN
234
235 This is a special option, and is just a shortcut for UNDEF | SCALAR.
236
237 * HANDLE
238
239 This option is also special, and is just a shortcut for GLOB |
240 GLOBREF. However, it seems likely that most people interested in
241 either globs or glob references are likely to really be interested in
242 whether the parameter in question could be a valid file or directory
243 handle.
244
245 To specify that a parameter must be of a given type when using named
246 parameters, do this:
247
248 validate(
249 @_, {
250 foo => { type => SCALAR },
251 bar => { type => HASHREF }
252 }
253 );
254
255 If a parameter can be of more than one type, just use the bitwise or
256 (|) operator to combine them.
257
258 validate( @_, { foo => { type => GLOB | GLOBREF } );
259
260 For positional parameters, this can be specified as follows:
261
262 validate_pos( @_, { type => SCALAR | ARRAYREF }, { type => CODEREF } );
263
264 Interface Validation
265
266 To specify that a parameter is expected to have a certain set of
267 methods, we can do the following:
268
20 }
21
22 # takes positional params
23 sub bar {
24 # first two are mandatory, third is optional
25 validate_pos( @_, 1, 1, 0 );
26 }
27
28 sub foo2 {
26929 validate(
27030 @_, {
27131 foo =>
272 # just has to be able to ->bar
273 { can => 'bar' }
32 # specify a type
33 { type => ARRAYREF },
34 bar =>
35 # specify an interface
36 { can => [ 'print', 'flush', 'frobnicate' ] },
37 baz => {
38 type => SCALAR, # a scalar ...
39 # ... that is a plain integer ...
40 regex => qr/^\d+$/,
41 callbacks => { # ... and smaller than 90
42 'less than 90' => sub { shift() < 90 },
43 },
44 }
27445 }
27546 );
276
277 ... or ...
278
279 validate(
280 @_, {
281 foo =>
282 # must be able to ->bar and ->print
283 { can => [qw( bar print )] }
284 }
285 );
286
287 Class Validation
288
289 A word of warning. When constructing your external interfaces, it is
290 probably better to specify what methods you expect an object to have
291 rather than what class it should be of (or a child of). This will make
292 your API much more flexible.
293
294 With that said, if you want to validate that an incoming parameter
295 belongs to a class (or child class) or classes, do:
296
297 validate(
298 @_,
299 { foo => { isa => 'My::Frobnicator' } }
300 );
301
302 ... or ...
303
304 validate(
305 @_,
306 # must be both, not either!
307 { foo => { isa => [qw( My::Frobnicator IO::Handle )] } }
308 );
309
310 Regex Validation
311
312 If you want to specify that a given parameter must match a specific
313 regular expression, this can be done with "regex" spec key. For
314 example:
315
316 validate(
317 @_,
318 { foo => { regex => qr/^\d+$/ } }
319 );
320
321 The value of the "regex" key may be either a string or a pre-compiled
322 regex created via qr.
323
324 If the value being checked against a regex is undefined, the regex is
325 explicitly checked against the empty string ('') instead, in order to
326 avoid "Use of uninitialized value" warnings.
327
328 The Regexp::Common module on CPAN is an excellent source of regular
329 expressions suitable for validating input.
330
331 Callback Validation
332
333 If none of the above are enough, it is possible to pass in one or more
334 callbacks to validate the parameter. The callback will be given the
335 value of the parameter as its first argument. Its second argument will
336 be all the parameters, as a reference to either a hash or array.
337 Callbacks are specified as hash reference. The key is an id for the
338 callback (used in error messages) and the value is a subroutine
339 reference, such as:
340
47 }
48
49 sub callback_with_custom_error {
34150 validate(
34251 @_,
34352 {
344 foo => {
345 callbacks => {
346 'smaller than a breadbox' => sub { shift() < $breadbox },
347 'green or blue' => sub {
348 return 1 if $_[0] eq 'green' || $_[0] eq 'blue';
349 die "$_[0] is not green or blue!";
350 }
53 foo => callbacks => {
54 'is an integer' => sub {
55 return 1 if $_[0] =~ /^-?[1-9][0-9]*$/;
56 die "$_[0] is not a valid integer value";
57 },
58 }
59 }
60 );
61 }
62
63 sub with_defaults {
64 my %p = validate(
65 @_, {
66 # required
67 foo => 1,
68 # $p{bar} will be 99 if bar is not given. bar is now
69 # optional.
70 bar => { default => 99 }
71 }
72 );
73 }
74
75 sub pos_with_defaults {
76 my @p = validate_pos( @_, 1, { default => 99 } );
77 }
78
79 sub sets_options_on_call {
80 my %p = validate_with(
81 params => \@_,
82 spec => { foo => { type => SCALAR, default => 2 } },
83 normalize_keys => sub { $_[0] =~ s/^-//; lc $_[0] },
84 );
85 }
86
87 # DESCRIPTION
88
89 The Params::Validate module allows you to validate method or function
90 call parameters to an arbitrary level of specificity. At the simplest
91 level, it is capable of validating the required parameters were given
92 and that no unspecified additional parameters were passed in.
93
94 It is also capable of determining that a parameter is of a specific
95 type, that it is an object of a certain class hierarchy, that it
96 possesses certain methods, or applying validation callbacks to
97 arguments.
98
99 ## EXPORT
100
101 The module always exports the `validate()` and `validate_pos()`
102 functions.
103
104 It also has an additional function available for export,
105 `validate_with`, which can be used to validate any type of
106 parameters, and set various options on a per-invocation basis.
107
108 In addition, it can export the following constants, which are used as
109 part of the type checking. These are `SCALAR`, `ARRAYREF`,
110 `HASHREF`, `CODEREF`, `GLOB`, `GLOBREF`, and `SCALARREF`,
111 `UNDEF`, `OBJECT`, `BOOLEAN`, and `HANDLE`. These are explained
112 in the section on [Type Validation](https://metacpan.org/pod/Params::Validate#Type-Validation).
113
114 The constants are available via the export tag `:types`. There is
115 also an `:all` tag which includes all of the constants as well as the
116 `validation_options()` function.
117
118 # PARAMETER VALIDATION
119
120 The validation mechanisms provided by this module can handle both
121 named or positional parameters. For the most part, the same features
122 are available for each. The biggest difference is the way that the
123 validation specification is given to the relevant subroutine. The
124 other difference is in the error messages produced when validation
125 checks fail.
126
127 When handling named parameters, the module will accept either a hash
128 or a hash reference.
129
130 Subroutines expecting named parameters should call the `validate()`
131 subroutine like this:
132
133 validate(
134 @_, {
135 parameter1 => validation spec,
136 parameter2 => validation spec,
137 ...
138 }
139 );
140
141 Subroutines expecting positional parameters should call the
142 `validate_pos()` subroutine like this:
143
144 validate_pos( @_, { validation spec }, { validation spec } );
145
146 ## Mandatory/Optional Parameters
147
148 If you just want to specify that some parameters are mandatory and
149 others are optional, this can be done very simply.
150
151 For a subroutine expecting named parameters, you would do this:
152
153 validate( @_, { foo => 1, bar => 1, baz => 0 } );
154
155 This says that the "foo" and "bar" parameters are mandatory and that
156 the "baz" parameter is optional. The presence of any other
157 parameters will cause an error.
158
159 For a subroutine expecting positional parameters, you would do this:
160
161 validate_pos( @_, 1, 1, 0, 0 );
162
163 This says that you expect at least 2 and no more than 4 parameters.
164 If you have a subroutine that has a minimum number of parameters but
165 can take any maximum number, you can do this:
166
167 validate_pos( @_, 1, 1, (0) x (@_ - 2) );
168
169 This will always be valid as long as at least two parameters are
170 given. A similar construct could be used for the more complex
171 validation parameters described further on.
172
173 Please note that this:
174
175 validate_pos( @_, 1, 1, 0, 1, 1 );
176
177 makes absolutely no sense, so don't do it. Any zeros must come at the
178 end of the validation specification.
179
180 In addition, if you specify that a parameter can have a default, then
181 it is considered optional.
182
183 ## Type Validation
184
185 This module supports the following simple types, which can be
186 [exported as constants](#export):
187
188 - SCALAR
189
190 A scalar which is not a reference, such as `10` or `'hello'`. A
191 parameter that is undefined is **not** treated as a scalar. If you
192 want to allow undefined values, you will have to specify `SCALAR |
193 UNDEF`.
194
195 - ARRAYREF
196
197 An array reference such as `[1, 2, 3]` or `\@foo`.
198
199 - HASHREF
200
201 A hash reference such as `{ a => 1, b => 2 }` or `\%bar`.
202
203 - CODEREF
204
205 A subroutine reference such as `\&foo_sub` or `sub { print "hello" }`.
206
207 - GLOB
208
209 This one is a bit tricky. A glob would be something like `*FOO`, but
210 not `\*FOO`, which is a glob reference. It should be noted that this
211 trick:
212
213 my $fh = do { local *FH; };
214
215 makes `$fh` a glob, not a glob reference. On the other hand, the
216 return value from `Symbol::gensym` is a glob reference. Either can
217 be used as a file or directory handle.
218
219 - GLOBREF
220
221 A glob reference such as `\*FOO`. See the [GLOB](https://metacpan.org/pod/GLOB) entry above
222 for more details.
223
224 - SCALARREF
225
226 A reference to a scalar such as `\$x`.
227
228 - UNDEF
229
230 An undefined value
231
232 - OBJECT
233
234 A blessed reference.
235
236 - BOOLEAN
237
238 This is a special option, and is just a shortcut for `UNDEF | SCALAR`.
239
240 - HANDLE
241
242 This option is also special, and is just a shortcut for `GLOB |
243 GLOBREF`. However, it seems likely that most people interested in
244 either globs or glob references are likely to really be interested in
245 whether the parameter in question could be a valid file or directory
246 handle.
247
248 To specify that a parameter must be of a given type when using named
249 parameters, do this:
250
251 validate(
252 @_, {
253 foo => { type => SCALAR },
254 bar => { type => HASHREF }
255 }
256 );
257
258 If a parameter can be of more than one type, just use the bitwise or
259 (`|`) operator to combine them.
260
261 validate( @_, { foo => { type => GLOB | GLOBREF } );
262
263 For positional parameters, this can be specified as follows:
264
265 validate_pos( @_, { type => SCALAR | ARRAYREF }, { type => CODEREF } );
266
267 ## Interface Validation
268
269 To specify that a parameter is expected to have a certain set of
270 methods, we can do the following:
271
272 validate(
273 @_, {
274 foo =>
275 # just has to be able to ->bar
276 { can => 'bar' }
277 }
278 );
279
280 ... or ...
281
282 validate(
283 @_, {
284 foo =>
285 # must be able to ->bar and ->print
286 { can => [qw( bar print )] }
287 }
288 );
289
290 ## Class Validation
291
292 A word of warning. When constructing your external interfaces, it is
293 probably better to specify what methods you expect an object to
294 have rather than what class it should be of (or a child of). This
295 will make your API much more flexible.
296
297 With that said, if you want to validate that an incoming parameter
298 belongs to a class (or child class) or classes, do:
299
300 validate(
301 @_,
302 { foo => { isa => 'My::Frobnicator' } }
303 );
304
305 ... or ...
306
307 validate(
308 @_,
309 # must be both, not either!
310 { foo => { isa => [qw( My::Frobnicator IO::Handle )] } }
311 );
312
313 ## Regex Validation
314
315 If you want to specify that a given parameter must match a specific
316 regular expression, this can be done with "regex" spec key. For
317 example:
318
319 validate(
320 @_,
321 { foo => { regex => qr/^\d+$/ } }
322 );
323
324 The value of the "regex" key may be either a string or a pre-compiled
325 regex created via `qr`.
326
327 If the value being checked against a regex is undefined, the regex is
328 explicitly checked against the empty string ('') instead, in order to
329 avoid "Use of uninitialized value" warnings.
330
331 The `Regexp::Common` module on CPAN is an excellent source of regular
332 expressions suitable for validating input.
333
334 ## Callback Validation
335
336 If none of the above are enough, it is possible to pass in one or more
337 callbacks to validate the parameter. The callback will be given the
338 **value** of the parameter as its first argument. Its second argument
339 will be all the parameters, as a reference to either a hash or array.
340 Callbacks are specified as hash reference. The key is an id for the
341 callback (used in error messages) and the value is a subroutine
342 reference, such as:
343
344 validate(
345 @_,
346 {
347 foo => {
348 callbacks => {
349 'smaller than a breadbox' => sub { shift() < $breadbox },
350 'green or blue' => sub {
351 return 1 if $_[0] eq 'green' || $_[0] eq 'blue';
352 die "$_[0] is not green or blue!";
351353 }
352354 }
353355 }
354 );
355
356 validate(
357 @_, {
358 foo => {
359 callbacks => {
360 'bigger than baz' => sub { $_[0] > $_[1]->{baz} }
361 }
356 }
357 );
358
359 validate(
360 @_, {
361 foo => {
362 callbacks => {
363 'bigger than baz' => sub { $_[0] > $_[1]->{baz} }
362364 }
363365 }
364 );
365
366 The callback should return a true value if the value is valid. If not,
367 it can return false or die. If you return false, a generic error
368 message will be thrown by Params::Validate.
369
370 If your callback dies instead you can provide a custom error message.
371 If the callback dies with a plain string, this string will be appended
372 to an exception message generated by Params::Validate. If the callback
373 dies with a reference (blessed or not), then this will be rethrown
374 as-is by Params::Validate.
375
376 Untainting
377
378 If you want values untainted, set the "untaint" key in a spec hashref
379 to a true value, like this:
380
381 my %p = validate(
366 }
367 );
368
369 The callback should return a true value if the value is valid. If not, it can
370 return false or die. If you return false, a generic error message will be
371 thrown by `Params::Validate`.
372
373 If your callback dies instead you can provide a custom error message. If the
374 callback dies with a plain string, this string will be appended to an
375 exception message generated by `Params::Validate`. If the callback dies with
376 a reference (blessed or not), then this will be rethrown as-is by
377 `Params::Validate`.
378
379 ## Untainting
380
381 If you want values untainted, set the "untaint" key in a spec hashref
382 to a true value, like this:
383
384 my %p = validate(
385 @_, {
386 foo => { type => SCALAR, untaint => 1 },
387 bar => { type => ARRAYREF }
388 }
389 );
390
391 This will untaint the "foo" parameter if the parameters are valid.
392
393 Note that untainting is only done if _all parameters_ are valid.
394 Also, only the return values are untainted, not the original values
395 passed into the validation function.
396
397 Asking for untainting of a reference value will not do anything, as
398 `Params::Validate` will only attempt to untaint the reference itself.
399
400 ## Mandatory/Optional Revisited
401
402 If you want to specify something such as type or interface, plus the
403 fact that a parameter can be optional, do this:
404
405 validate(
406 @_, {
407 foo => { type => SCALAR },
408 bar => { type => ARRAYREF, optional => 1 }
409 }
410 );
411
412 or this for positional parameters:
413
414 validate_pos(
415 @_,
416 { type => SCALAR },
417 { type => ARRAYREF, optional => 1 }
418 );
419
420 By default, parameters are assumed to be mandatory unless specified as
421 optional.
422
423 ## Dependencies
424
425 It also possible to specify that a given optional parameter depends on
426 the presence of one or more other optional parameters.
427
428 validate(
429 @_, {
430 cc_number => {
431 type => SCALAR,
432 optional => 1,
433 depends => [ 'cc_expiration', 'cc_holder_name' ],
434 },
435 cc_expiration => { type => SCALAR, optional => 1 },
436 cc_holder_name => { type => SCALAR, optional => 1 },
437 }
438 );
439
440 In this case, "cc\_number", "cc\_expiration", and "cc\_holder\_name" are
441 all optional. However, if "cc\_number" is provided, then
442 "cc\_expiration" and "cc\_holder\_name" must be provided as well.
443
444 This allows you to group together sets of parameters that all must be
445 provided together.
446
447 The `validate_pos()` version of dependencies is slightly different,
448 in that you can only depend on one other parameter. Also, if for
449 example, the second parameter 2 depends on the fourth parameter, then
450 it implies a dependency on the third parameter as well. This is
451 because if the fourth parameter is required, then the user must also
452 provide a third parameter so that there can be four parameters in
453 total.
454
455 `Params::Validate` will die if you try to depend on a parameter not
456 declared as part of your parameter specification.
457
458 ## Specifying defaults
459
460 If the `validate()` or `validate_pos()` functions are called in a list
461 context, they will return a hash or containing the original parameters plus
462 defaults as indicated by the validation spec.
463
464 If the function is not called in a list context, providing a default
465 in the validation spec still indicates that the parameter is optional.
466
467 The hash or array returned from the function will always be a copy of
468 the original parameters, in order to leave `@_` untouched for the
469 calling function.
470
471 Simple examples of defaults would be:
472
473 my %p = validate( @_, { foo => 1, bar => { default => 99 } } );
474
475 my @p = validate_pos( @_, 1, { default => 99 } );
476
477 In scalar context, a hash reference or array reference will be
478 returned, as appropriate.
479
480 # USAGE NOTES
481
482 ## Validation failure
483
484 By default, when validation fails `Params::Validate` calls
485 `Carp::confess()`. This can be overridden by setting the `on_fail`
486 option, which is described in the ["GLOBAL" OPTIONS](https://metacpan.org/pod/&#x22;GLOBAL&#x22;&#x20;OPTIONS)
487 section.
488
489 ## Method calls
490
491 When using this module to validate the parameters passed to a method
492 call, you will probably want to remove the class/object from the
493 parameter list **before** calling `validate()` or `validate_pos()`.
494 If your method expects named parameters, then this is necessary for
495 the `validate()` function to actually work, otherwise `@_` will not
496 be usable as a hash, because it will first have your object (or
497 class) **followed** by a set of keys and values.
498
499 Thus the idiomatic usage of `validate()` in a method call will look
500 something like this:
501
502 sub method {
503 my $self = shift;
504
505 my %params = validate(
382506 @_, {
383 foo => { type => SCALAR, untaint => 1 },
384 bar => { type => ARRAYREF }
507 foo => 1,
508 bar => { type => ARRAYREF },
385509 }
386510 );
387
388 This will untaint the "foo" parameter if the parameters are valid.
389
390 Note that untainting is only done if all parameters are valid. Also,
391 only the return values are untainted, not the original values passed
392 into the validation function.
393
394 Asking for untainting of a reference value will not do anything, as
395 Params::Validate will only attempt to untaint the reference itself.
396
397 Mandatory/Optional Revisited
398
399 If you want to specify something such as type or interface, plus the
400 fact that a parameter can be optional, do this:
401
402 validate(
403 @_, {
404 foo => { type => SCALAR },
405 bar => { type => ARRAYREF, optional => 1 }
406 }
407 );
408
409 or this for positional parameters:
410
411 validate_pos(
412 @_,
413 { type => SCALAR },
414 { type => ARRAYREF, optional => 1 }
415 );
416
417 By default, parameters are assumed to be mandatory unless specified as
418 optional.
419
420 Dependencies
421
422 It also possible to specify that a given optional parameter depends on
423 the presence of one or more other optional parameters.
424
425 validate(
426 @_, {
427 cc_number => {
428 type => SCALAR,
429 optional => 1,
430 depends => [ 'cc_expiration', 'cc_holder_name' ],
431 },
432 cc_expiration => { type => SCALAR, optional => 1 },
433 cc_holder_name => { type => SCALAR, optional => 1 },
434 }
435 );
436
437 In this case, "cc_number", "cc_expiration", and "cc_holder_name" are
438 all optional. However, if "cc_number" is provided, then "cc_expiration"
439 and "cc_holder_name" must be provided as well.
440
441 This allows you to group together sets of parameters that all must be
442 provided together.
443
444 The validate_pos() version of dependencies is slightly different, in
445 that you can only depend on one other parameter. Also, if for example,
446 the second parameter 2 depends on the fourth parameter, then it implies
447 a dependency on the third parameter as well. This is because if the
448 fourth parameter is required, then the user must also provide a third
449 parameter so that there can be four parameters in total.
450
451 Params::Validate will die if you try to depend on a parameter not
452 declared as part of your parameter specification.
453
454 Specifying defaults
455
456 If the validate() or validate_pos() functions are called in a list
457 context, they will return a hash or containing the original parameters
458 plus defaults as indicated by the validation spec.
459
460 If the function is not called in a list context, providing a default in
461 the validation spec still indicates that the parameter is optional.
462
463 The hash or array returned from the function will always be a copy of
464 the original parameters, in order to leave @_ untouched for the calling
465 function.
466
467 Simple examples of defaults would be:
468
469 my %p = validate( @_, { foo => 1, bar => { default => 99 } } );
470
471 my @p = validate_pos( @_, 1, { default => 99 } );
472
473 In scalar context, a hash reference or array reference will be
474 returned, as appropriate.
475
476 USAGE NOTES
477
478 Validation failure
479
480 By default, when validation fails Params::Validate calls
481 Carp::confess(). This can be overridden by setting the on_fail option,
482 which is described in the "GLOBAL" OPTIONS section.
483
484 Method calls
485
486 When using this module to validate the parameters passed to a method
487 call, you will probably want to remove the class/object from the
488 parameter list before calling validate() or validate_pos(). If your
489 method expects named parameters, then this is necessary for the
490 validate() function to actually work, otherwise @_ will not be usable
491 as a hash, because it will first have your object (or class) followed
492 by a set of keys and values.
493
494 Thus the idiomatic usage of validate() in a method call will look
495 something like this:
496
497 sub method {
498 my $self = shift;
499
500 my %params = validate(
501 @_, {
502 foo => 1,
503 bar => { type => ARRAYREF },
504 }
511 }
512
513 ## Speeding Up Validation
514
515 In most cases, the validation spec will remain the same for each call to a
516 subroutine. In that case, you can speed up validation by defining the
517 validation spec just once, rather than on each call to the subroutine:
518
519 my %spec = ( ... );
520 sub foo {
521 my %params = validate( @_, \%spec );
522 }
523
524 You can also use the `state` feature to do this:
525
526 use feature 'state';
527
528 sub foo {
529 state $spec = { ... };
530 my %params = validate( @_, $spec );
531 }
532
533 # "GLOBAL" OPTIONS
534
535 Because the API for the `validate()` and `validate_pos()` functions does not
536 make it possible to specify any options other than the validation spec, it is
537 possible to set some options as pseudo-'globals'. These allow you to specify
538 such things as whether or not the validation of named parameters should be
539 case sensitive, for one example.
540
541 These options are called pseudo-'globals' because these settings are
542 **only applied to calls originating from the package that set the
543 options**.
544
545 In other words, if I am in package `Foo` and I call
546 `validation_options()`, those options are only in effect when I call
547 `validate()` from package `Foo`.
548
549 While this is quite different from how most other modules operate, I
550 feel that this is necessary in able to make it possible for one
551 module/application to use Params::Validate while still using other
552 modules that also use Params::Validate, perhaps with different
553 options set.
554
555 The downside to this is that if you are writing an app with a standard
556 calling style for all functions, and your app has ten modules, **each
557 module must include a call to `validation_options()`**. You could of
558 course write a module that all your modules use which uses various
559 trickery to do this when imported.
560
561 ## Options
562
563 - normalize\_keys => $callback
564
565 This option is only relevant when dealing with named parameters.
566
567 This callback will be used to transform the hash keys of both the
568 parameters and the parameter spec when `validate()` or
569 `validate_with()` are called.
570
571 Any alterations made by this callback will be reflected in the
572 parameter hash that is returned by the validation function. For
573 example:
574
575 sub foo {
576 return validate_with(
577 params => \@_,
578 spec => { foo => { type => SCALAR } },
579 normalize_keys =>
580 sub { my $k = shift; $k =~ s/^-//; return uc $k },
505581 );
582
506583 }
507584
508 Speeding Up Validation
509
510 In most cases, the validation spec will remain the same for each call
511 to a subroutine. In that case, you can speed up validation by defining
512 the validation spec just once, rather than on each call to the
513 subroutine:
514
515 my %spec = ( ... );
516 sub foo {
517 my %params = validate( @_, \%spec );
518 }
519
520 You can also use the state feature to do this:
521
522 use feature 'state';
523
524 sub foo {
525 state $spec = { ... };
526 my %params = validate( @_, $spec );
527 }
528
529 "GLOBAL" OPTIONS
530
531 Because the API for the validate() and validate_pos() functions does
532 not make it possible to specify any options other than the validation
533 spec, it is possible to set some options as pseudo-'globals'. These
534 allow you to specify such things as whether or not the validation of
535 named parameters should be case sensitive, for one example.
536
537 These options are called pseudo-'globals' because these settings are
538 only applied to calls originating from the package that set the
539 options.
540
541 In other words, if I am in package Foo and I call validation_options(),
542 those options are only in effect when I call validate() from package
543 Foo.
544
545 While this is quite different from how most other modules operate, I
546 feel that this is necessary in able to make it possible for one
547 module/application to use Params::Validate while still using other
548 modules that also use Params::Validate, perhaps with different options
549 set.
550
551 The downside to this is that if you are writing an app with a standard
552 calling style for all functions, and your app has ten modules, each
553 module must include a call to validation_options(). You could of course
554 write a module that all your modules use which uses various trickery to
555 do this when imported.
556
557 Options
558
559 * normalize_keys => $callback
560
561 This option is only relevant when dealing with named parameters.
562
563 This callback will be used to transform the hash keys of both the
564 parameters and the parameter spec when validate() or validate_with()
565 are called.
566
567 Any alterations made by this callback will be reflected in the
568 parameter hash that is returned by the validation function. For
569 example:
570
571 sub foo {
572 return validate_with(
573 params => \@_,
574 spec => { foo => { type => SCALAR } },
575 normalize_keys =>
576 sub { my $k = shift; $k =~ s/^-//; return uc $k },
577 );
578
579 }
580
581 %p = foo( foo => 20 );
582
583 # $p{FOO} is now 20
584
585 %p = foo( -fOo => 50 );
586
587 # $p{FOO} is now 50
588
589 The callback must return a defined value.
590
591 If a callback is given then the deprecated "ignore_case" and
592 "strip_leading" options are ignored.
593
594 * allow_extra => $boolean
595
596 If true, then the validation routine will allow extra parameters not
597 named in the validation specification. In the case of positional
598 parameters, this allows an unlimited number of maximum parameters
599 (though a minimum may still be set). Defaults to false.
600
601 * on_fail => $callback
602
603 If given, this callback will be called whenever a validation check
604 fails. It will be called with a single parameter, which will be a
605 string describing the failure. This is useful if you wish to have
606 this module throw exceptions as objects rather than as strings, for
607 example.
608
609 This callback is expected to die() internally. If it does not, the
610 validation will proceed onwards, with unpredictable results.
611
612 The default is to simply use the Carp module's confess() function.
613
614 * stack_skip => $number
615
616 This tells Params::Validate how many stack frames to skip when
617 finding a subroutine name to use in error messages. By default, it
618 looks one frame back, at the immediate caller to validate() or
619 validate_pos(). If this option is set, then the given number of
620 frames are skipped instead.
621
622 * ignore_case => $boolean
623
624 DEPRECATED
625
626 This is only relevant when dealing with named parameters. If it is
627 true, then the validation code will ignore the case of parameter
628 names. Defaults to false.
629
630 * strip_leading => $characters
631
632 DEPRECATED
633
634 This too is only relevant when dealing with named parameters. If this
635 is given then any parameters starting with these characters will be
636 considered equivalent to parameters without them entirely. For
637 example, if this is specified as '-', then -foo and foo would be
638 considered identical.
639
640 PER-INVOCATION OPTIONS
641
642 The validate_with() function can be used to set the options listed
643 above on a per-invocation basis. For example:
644
645 my %p = validate_with(
646 params => \@_,
647 spec => {
648 foo => { type => SCALAR },
649 bar => { default => 10 }
650 },
651 allow_extra => 1,
652 );
653
654 In addition to the options listed above, it is also possible to set the
655 option "called", which should be a string. This string will be used in
656 any error messages caused by a failure to meet the validation spec.
657
658 This subroutine will validate named parameters as a hash if the "spec"
659 parameter is a hash reference. If it is an array reference, the
660 parameters are assumed to be positional.
661
662 my %p = validate_with(
663 params => \@_,
664 spec => {
665 foo => { type => SCALAR },
666 bar => { default => 10 }
667 },
668 allow_extra => 1,
669 called => 'The Quux::Baz class constructor',
670 );
671
672 my @p = validate_with(
673 params => \@_,
674 spec => [
675 { type => SCALAR },
676 { default => 10 }
677 ],
678 allow_extra => 1,
679 called => 'The Quux::Baz class constructor',
680 );
681
682 DISABLING VALIDATION
683
684 If the environment variable PERL_NO_VALIDATION is set to something
685 true, then validation is turned off. This may be useful if you only
686 want to use this module during development but don't want the speed hit
687 during production.
688
689 The only error that will be caught will be when an odd number of
690 parameters are passed into a function/method that expects a hash.
691
692 If you want to selectively turn validation on and off at runtime, you
693 can directly set the $Params::Validate::NO_VALIDATION global variable.
694 It is strongly recommended that you localize any changes to this
695 variable, because other modules you are using may expect validation to
696 be on when they execute. For example:
697
698 {
699 local $Params::Validate::NO_VALIDATION = 1;
700
701 # no error
702 foo( bar => 2 );
703 }
704
705 # error
585 %p = foo( foo => 20 );
586
587 # $p{FOO} is now 20
588
589 %p = foo( -fOo => 50 );
590
591 # $p{FOO} is now 50
592
593 The callback must return a defined value.
594
595 If a callback is given then the deprecated "ignore\_case" and
596 "strip\_leading" options are ignored.
597
598 - allow\_extra => $boolean
599
600 If true, then the validation routine will allow extra parameters not
601 named in the validation specification. In the case of positional
602 parameters, this allows an unlimited number of maximum parameters
603 (though a minimum may still be set). Defaults to false.
604
605 - on\_fail => $callback
606
607 If given, this callback will be called whenever a validation check
608 fails. It will be called with a single parameter, which will be a
609 string describing the failure. This is useful if you wish to have
610 this module throw exceptions as objects rather than as strings, for
611 example.
612
613 This callback is expected to `die()` internally. If it does not, the
614 validation will proceed onwards, with unpredictable results.
615
616 The default is to simply use the Carp module's `confess()` function.
617
618 - stack\_skip => $number
619
620 This tells Params::Validate how many stack frames to skip when finding
621 a subroutine name to use in error messages. By default, it looks one
622 frame back, at the immediate caller to `validate()` or
623 `validate_pos()`. If this option is set, then the given number of
624 frames are skipped instead.
625
626 - ignore\_case => $boolean
627
628 DEPRECATED
629
630 This is only relevant when dealing with named parameters. If it is
631 true, then the validation code will ignore the case of parameter
632 names. Defaults to false.
633
634 - strip\_leading => $characters
635
636 DEPRECATED
637
638 This too is only relevant when dealing with named parameters. If this
639 is given then any parameters starting with these characters will be
640 considered equivalent to parameters without them entirely. For
641 example, if this is specified as '-', then `-foo` and `foo` would be
642 considered identical.
643
644 # PER-INVOCATION OPTIONS
645
646 The `validate_with()` function can be used to set the options listed
647 above on a per-invocation basis. For example:
648
649 my %p = validate_with(
650 params => \@_,
651 spec => {
652 foo => { type => SCALAR },
653 bar => { default => 10 }
654 },
655 allow_extra => 1,
656 );
657
658 In addition to the options listed above, it is also possible to set
659 the option "called", which should be a string. This string will be
660 used in any error messages caused by a failure to meet the validation
661 spec.
662
663 This subroutine will validate named parameters as a hash if the "spec"
664 parameter is a hash reference. If it is an array reference, the
665 parameters are assumed to be positional.
666
667 my %p = validate_with(
668 params => \@_,
669 spec => {
670 foo => { type => SCALAR },
671 bar => { default => 10 }
672 },
673 allow_extra => 1,
674 called => 'The Quux::Baz class constructor',
675 );
676
677 my @p = validate_with(
678 params => \@_,
679 spec => [
680 { type => SCALAR },
681 { default => 10 }
682 ],
683 allow_extra => 1,
684 called => 'The Quux::Baz class constructor',
685 );
686
687 # DISABLING VALIDATION
688
689 If the environment variable `PERL_NO_VALIDATION` is set to something
690 true, then validation is turned off. This may be useful if you only
691 want to use this module during development but don't want the speed
692 hit during production.
693
694 The only error that will be caught will be when an odd number of
695 parameters are passed into a function/method that expects a hash.
696
697 If you want to selectively turn validation on and off at runtime, you
698 can directly set the `$Params::Validate::NO_VALIDATION` global
699 variable. It is **strongly** recommended that you **localize** any
700 changes to this variable, because other modules you are using may
701 expect validation to be on when they execute. For example:
702
703 {
704 local $Params::Validate::NO_VALIDATION = 1;
705
706 # no error
706707 foo( bar => 2 );
707
708 sub foo {
709 my %p = validate( @_, { foo => 1 } );
710 ...;
711 }
712
713 But if you want to shoot yourself in the foot and just turn it off, go
714 ahead!
715
716 SPECIFYING AN IMPLEMENTATION
717
718 This module ships with two equivalent implementations, one in XS and
719 one in pure Perl. By default, it will try to load the XS version and
720 fall back to the pure Perl implementation as needed. If you want to
721 request a specific version, you can set the
722 PARAMS_VALIDATE_IMPLEMENTATION environment variable to either XS or PP.
723 If the implementation you ask for cannot be loaded, then this module
724 will die when loaded.
725
726 TAINT MODE
727
728 The XS implementation of this module has some problems Under taint mode
729 with version of Perl before 5.14. If validation fails, then instead of
730 getting the expected error message you'll get a message like "Insecure
731 dependency in eval_sv". This can be worked around by either untainting
732 the arguments yourself, using the pure Perl implementation, or
733 upgrading your Perl.
734
735 LIMITATIONS
736
737 Right now there is no way (short of a callback) to specify that
738 something must be of one of a list of classes, or that it must possess
739 one of a list of methods. If this is desired, it can be added in the
740 future.
741
742 Ideally, there would be only one validation function. If someone
743 figures out how to do this, please let me know.
744
745 SUPPORT
746
747 Please submit bugs and patches to the CPAN RT system at
748 http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Params%3A%3AValidate or
749 via email at bug-params-validate@rt.cpan.org.
750
751 Support questions can be sent to Dave at autarch@urth.org.
752
753 DONATIONS
754
755 If you'd like to thank me for the work I've done on this module, please
756 consider making a "donation" to me via PayPal. I spend a lot of free
757 time creating free software, and would appreciate any support you'd
758 care to offer.
759
760 Please note that I am not suggesting that you must do this in order for
761 me to continue working on this particular software. I will continue to
762 do so, inasmuch as I have in the past, for as long as it interests me.
763
764 Similarly, a donation made in this way will probably not make me work
765 on this software much more, unless I get so many donations that I can
766 consider working on free software full time, which seems unlikely at
767 best.
768
769 To donate, log into PayPal and send money to autarch@urth.org or use
770 the button on this page: http://www.urth.org/~autarch/fs-donation.html
771
772 AUTHORS
773
774 * Dave Rolsky <autarch@urth.org>
775
776 * Ilya Martynov <ilya@martynov.org>
777
778 CONTRIBUTORS
779
780 * Ivan Bessarabov <ivan@bessarabov.ru>
781
782 * J.R. Mash <jmash.code@gmail.com>
783
784 * Noel Maddy <zhtwnpanta@gmail.com>
785
786 * Olivier Mengué <dolmen@cpan.org>
787
788 * Vincent Pit <perl@profvince.com>
789
790 COPYRIGHT AND LICENSE
791
792 This software is Copyright (c) 2001 - 2016 by Dave Rolsky and Ilya
793 Martynov.
794
795 This is free software, licensed under:
796
797 The Artistic License 2.0 (GPL Compatible)
798
708 }
709
710 # error
711 foo( bar => 2 );
712
713 sub foo {
714 my %p = validate( @_, { foo => 1 } );
715 ...;
716 }
717
718 But if you want to shoot yourself in the foot and just turn it off, go
719 ahead!
720
721 # SPECIFYING AN IMPLEMENTATION
722
723 This module ships with two equivalent implementations, one in XS and one in
724 pure Perl. By default, it will try to load the XS version and fall back to the
725 pure Perl implementation as needed. If you want to request a specific version,
726 you can set the `PARAMS_VALIDATE_IMPLEMENTATION` environment variable to
727 either `XS` or `PP`. If the implementation you ask for cannot be loaded,
728 then this module will die when loaded.
729
730 # TAINT MODE
731
732 The XS implementation of this module has some problems Under taint mode with
733 versions of Perl before 5.14. If validation _fails_, then instead of getting
734 the expected error message you'll get a message like "Insecure dependency in
735 eval\_sv". This can be worked around by either untainting the arguments
736 yourself, using the pure Perl implementation, or upgrading your Perl.
737
738 # LIMITATIONS
739
740 Right now there is no way (short of a callback) to specify that
741 something must be of one of a list of classes, or that it must possess
742 one of a list of methods. If this is desired, it can be added in the
743 future.
744
745 Ideally, there would be only one validation function. If someone
746 figures out how to do this, please let me know.
747
748 # SUPPORT
749
750 Bugs may be submitted through [the RT bug tracker](http://rt.cpan.org/Public/Dist/Display.html?Name=Params-Validate)
751 (or [bug-params-validate@rt.cpan.org](mailto:bug-params-validate@rt.cpan.org)).
752
753 I am also usually active on IRC as 'drolsky' on `irc://irc.perl.org`.
754
755 # DONATIONS
756
757 If you'd like to thank me for the work I've done on this module, please
758 consider making a "donation" to me via PayPal. I spend a lot of free time
759 creating free software, and would appreciate any support you'd care to offer.
760
761 Please note that **I am not suggesting that you must do this** in order for me
762 to continue working on this particular software. I will continue to do so,
763 inasmuch as I have in the past, for as long as it interests me.
764
765 Similarly, a donation made in this way will probably not make me work on this
766 software much more, unless I get so many donations that I can consider working
767 on free software full time (let's all have a chuckle at that together).
768
769 To donate, log into PayPal and send money to autarch@urth.org, or use the
770 button at [http://www.urth.org/~autarch/fs-donation.html](http://www.urth.org/~autarch/fs-donation.html).
771
772 # AUTHORS
773
774 - Dave Rolsky &lt;autarch@urth.org>
775 - Ilya Martynov &lt;ilya@martynov.org>
776
777 # CONTRIBUTORS
778
779 - Ivan Bessarabov &lt;ivan@bessarabov.ru>
780 - J.R. Mash &lt;jmash.code@gmail.com>
781 - Noel Maddy &lt;zhtwnpanta@gmail.com>
782 - Olivier Mengué &lt;dolmen@cpan.org>
783 - Tony Cook &lt;tony@develop-help.com>
784 - Vincent Pit &lt;perl@profvince.com>
785
786 # COPYRIGHT AND LICENCE
787
788 This software is Copyright (c) 2001 - 2016 by Dave Rolsky and Ilya Martynov.
789
790 This is free software, licensed under:
791
792 The Artistic License 2.0 (GPL Compatible)
00 requires "Carp" => "0";
11 requires "Exporter" => "0";
2 requires "JSON::PP" => "2.27300";
32 requires "Module::Implementation" => "0";
43 requires "Scalar::Util" => "1.10";
54 requires "XSLoader" => "0";
3534 requires "Module::Build" => "0.28";
3635 };
3736
37 on 'configure' => sub {
38 suggests "JSON::PP" => "2.27300";
39 };
40
3841 on 'develop' => sub {
3942 requires "File::Spec" => "0";
4043 requires "IO::Handle" => "0";
2929 stopwords = pre
3030 stopwords = runtime
3131 -remove = MakeMaker
32 -remove = Test::CleanNamespaces
3233 -remove = Test::TidyAll
3334 -remove = Test::Version
3435
4344 [=inc::MyModuleBuild]
4445
4546 [PurePerlTests]
47 :version = 0.06
4648 env_var = PV_TEST_PERL
22 use strict;
33 use warnings;
44
5 our $VERSION = '1.22';
5 our $VERSION = '1.23';
66
77 our @ISA = 'Exporter';
88
22 use strict;
33 use warnings;
44
5 our $VERSION = '1.22';
5 our $VERSION = '1.23';
66
77 use Params::Validate::Constants;
88 use Scalar::Util 1.10 ();
22 use strict;
33 use warnings;
44
5 our $VERSION = '1.22';
5 our $VERSION = '1.23';
66
77 use Carp;
88
778778 ok = POPi;
779779 PUTBACK;
780780
781 if (!ok) {
781 if (! ok) {
782782 SV* buffer = newSVpvf(id, string_representation(value));
783783 SV *caller = get_caller(options);
784784
16061606 AV* pa;
16071607 HV* ph;
16081608 HV* options;
1609 IV ok;
16091610
16101611 if (no_validation() && GIMME_V == G_VOID) {
16111612 XSRETURN(0);
16421643 if (! ph) {
16431644 ph = (HV*) sv_2mortal((SV*) newHV());
16441645
1645 if (! convert_array2hash(pa, options, ph) ) {
1646 PUTBACK;
1647 ok = convert_array2hash(pa, options, ph);
1648 SPAGAIN;
1649
1650 if (!ok) {
16461651 XSRETURN(0);
16471652 }
16481653 }
16491654 if (GIMME_V != G_VOID) {
16501655 ret = (HV*) sv_2mortal((SV*) newHV());
16511656 }
1652 if (! validate(ph, (HV*) SvRV(specs), options, ret)) {
1657
1658 PUTBACK;
1659 ok = validate(ph, (HV*) SvRV(specs), options, ret);
1660 SPAGAIN;
1661
1662 if (! ok) {
16531663 XSRETURN(0);
16541664 }
1665
16551666 RETURN_HASH(ret);
16561667
16571668 void
16651676 AV* specs;
16661677 AV* ret = NULL;
16671678 IV i;
1679 IV ok;
16681680
16691681 if (no_validation() && GIMME_V == G_VOID) {
16701682 XSRETURN(0);
16881700 ret = (AV*) sv_2mortal((SV*) newAV());
16891701 }
16901702
1691 if (! validate_pos((AV*) SvRV(p), specs, get_options(NULL), ret)) {
1703 PUTBACK;
1704 ok = validate_pos((AV*) SvRV(p), specs, get_options(NULL), ret);
1705 SPAGAIN;
1706
1707 if (! ok) {
16921708 XSRETURN(0);
16931709 }
16941710
17031719 SV* params;
17041720 SV* spec;
17051721 IV i;
1722 IV ok;
17061723
17071724 if (no_validation() && GIMME_V == G_VOID) XSRETURN(0);
17081725
17391756 }
17401757
17411758 PUTBACK;
1742
1743 if (! validate_pos((AV*) SvRV(params), (AV*) SvRV(spec), get_options(p), ret)) {
1744 SPAGAIN;
1759 ok = validate_pos((AV*) SvRV(params), (AV*) SvRV(spec), get_options(p), ret);
1760 SPAGAIN;
1761
1762 if (! ok) {
17451763 XSRETURN(0);
17461764 }
17471765
1748 SPAGAIN;
17491766 RETURN_ARRAY(ret);
17501767 }
17511768 else {
17831800 if (! hv_set) {
17841801 hv = (HV*) sv_2mortal((SV*) newHV());
17851802
1786 if (! convert_array2hash((AV*) SvRV(params), options, hv))
1803 PUTBACK;
1804 ok = convert_array2hash((AV*) SvRV(params), options, hv);
1805 SPAGAIN;
1806
1807 if (!ok) {
17871808 XSRETURN(0);
1809 }
17881810 }
17891811 }
17901812 else {
17961818 }
17971819
17981820 PUTBACK;
1799
1800 if (! validate(hv, (HV*) SvRV(spec), options, ret)) {
1801 SPAGAIN;
1821 ok = validate(hv, (HV*) SvRV(spec), options, ret);
1822 SPAGAIN;
1823
1824 if (! ok) {
18021825 XSRETURN(0);
18031826 }
18041827
1805 SPAGAIN;
18061828 RETURN_HASH(ret);
18071829 }
18081830 else {
44 use strict;
55 use warnings;
66
7 our $VERSION = '1.22';
7 our $VERSION = '1.23';
88
99 use Exporter;
1010 use Module::Implementation;
6868
6969 =pod
7070
71 =encoding UTF-8
72
7173 =head1 NAME
7274
7375 Params::Validate - Validate method/function parameters
7476
7577 =head1 VERSION
7678
77 version 1.22
79 version 1.23
7880
7981 =head1 SYNOPSIS
8082
186188 also an C<:all> tag which includes all of the constants as well as the
187189 C<validation_options()> function.
188190
189 =encoding UTF-8
190
191191 =head1 PARAMETER VALIDATION
192192
193193 The validation mechanisms provided by this module can handle both
811811 =head1 TAINT MODE
812812
813813 The XS implementation of this module has some problems Under taint mode with
814 version of Perl before 5.14. If validation I<fails>, then instead of getting
814 versions of Perl before 5.14. If validation I<fails>, then instead of getting
815815 the expected error message you'll get a message like "Insecure dependency in
816816 eval_sv". This can be worked around by either untainting the arguments
817817 yourself, using the pure Perl implementation, or upgrading your Perl.
828828
829829 =head1 SUPPORT
830830
831 Please submit bugs and patches to the CPAN RT system at
832 http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Params%3A%3AValidate or
833 via email at bug-params-validate@rt.cpan.org.
834
835 Support questions can be sent to Dave at autarch@urth.org.
831 Bugs may be submitted through L<the RT bug tracker|http://rt.cpan.org/Public/Dist/Display.html?Name=Params-Validate>
832 (or L<bug-params-validate@rt.cpan.org|mailto:bug-params-validate@rt.cpan.org>).
833
834 I am also usually active on IRC as 'drolsky' on C<irc://irc.perl.org>.
836835
837836 =head1 DONATIONS
838837
839 If you'd like to thank me for the work I've done on this module,
840 please consider making a "donation" to me via PayPal. I spend a lot of
841 free time creating free software, and would appreciate any support
842 you'd care to offer.
843
844 Please note that B<I am not suggesting that you must do this> in order
845 for me to continue working on this particular software. I will
846 continue to do so, inasmuch as I have in the past, for as long as it
847 interests me.
848
849 Similarly, a donation made in this way will probably not make me work
850 on this software much more, unless I get so many donations that I can
851 consider working on free software full time, which seems unlikely at
852 best.
853
854 To donate, log into PayPal and send money to autarch@urth.org or use
855 the button on this page:
856 L<http://www.urth.org/~autarch/fs-donation.html>
838 If you'd like to thank me for the work I've done on this module, please
839 consider making a "donation" to me via PayPal. I spend a lot of free time
840 creating free software, and would appreciate any support you'd care to offer.
841
842 Please note that B<I am not suggesting that you must do this> in order for me
843 to continue working on this particular software. I will continue to do so,
844 inasmuch as I have in the past, for as long as it interests me.
845
846 Similarly, a donation made in this way will probably not make me work on this
847 software much more, unless I get so many donations that I can consider working
848 on free software full time (let's all have a chuckle at that together).
849
850 To donate, log into PayPal and send money to autarch@urth.org, or use the
851 button at L<http://www.urth.org/~autarch/fs-donation.html>.
857852
858853 =head1 AUTHORS
859854
871866
872867 =head1 CONTRIBUTORS
873868
874 =for stopwords Ivan Bessarabov J.R. Mash Noel Maddy Olivier Mengué Vincent Pit
869 =for stopwords Ivan Bessarabov J.R. Mash Noel Maddy Olivier Mengué Tony Cook Vincent Pit
875870
876871 =over 4
877872
893888
894889 =item *
895890
891 Tony Cook <tony@develop-help.com>
892
893 =item *
894
896895 Vincent Pit <perl@profvince.com>
897896
898897 =back
899898
900 =head1 COPYRIGHT AND LICENSE
899 =head1 COPYRIGHT AND LICENCE
901900
902901 This software is Copyright (c) 2001 - 2016 by Dave Rolsky and Ilya Martynov.
903902
00 package # hide from PAUSE
11 Params::Validate;
22
3 our $VERSION = '1.22';
3 our $VERSION = '1.23';
44
55 BEGIN { $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'PP' }
66 use Params::Validate;
00 package # hide from PAUSE
11 Params::Validate;
22
3 our $VERSION = '1.22';
3 our $VERSION = '1.23';
44
55 BEGIN { $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'XS' }
66 use Params::Validate;
66 'configure' => {
77 'requires' => {
88 'Module::Build' => '0.28'
9 },
10 'suggests' => {
11 'JSON::PP' => '2.27300'
912 }
1013 },
1114 'develop' => {
3841 'requires' => {
3942 'Carp' => '0',
4043 'Exporter' => '0',
41 'JSON::PP' => '2.27300',
4244 'Module::Implementation' => '0',
4345 'Scalar::Util' => '1.10',
4446 'XSLoader' => '0',
22 use strict;
33 use warnings;
44
5 # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.021
5 # This test was generated by Dist::Zilla::Plugin::Test::ReportPrereqs 0.024
66
77 use Test::More tests => 1;
88
1515 { type => SCALAR, optional => 1, default => 'must be second one' },
1616 );
1717
18 is( $first, undef, '01 no default for first' );
19 is( $second, 'must be second one', '01 default for second' );
18 is( $first, undef, 'no default for first parameter' );
19 is( $second, 'must be second one',
20 'default for second parameter is applied' );
2021 }
8888
8989 like(
9090 $e,
91 qr/\QThe 'string' parameter (\E.+?\Q) to main::validate4 did not pass the 'string' callback\E\s+at/,
91 qr/\QThe 'string' parameter (\E.+?\Q) to main::validate4 did not pass the 'string' callback/,
9292 'callback that does not dies generates a sane error message'
9393 );
9494 }
6161 't/39-reentrant.t',
6262 't/author-00-compile.t',
6363 't/author-eol.t',
64 't/author-memory-leak.t',
6465 't/author-mojibake.t',
6566 't/author-no-tabs.t',
6667 't/author-pod-spell.t',
6768 't/author-pod-syntax.t',
69 't/author-pp-01-validate.t',
70 't/author-pp-02-noop.t',
71 't/author-pp-04-defaults.t',
72 't/author-pp-05-noop_default.t',
73 't/author-pp-06-options.t',
74 't/author-pp-07-with.t',
75 't/author-pp-08-noop_with.t',
76 't/author-pp-09-regex.t',
77 't/author-pp-10-noop_regex.t',
78 't/author-pp-11-cb.t',
79 't/author-pp-12-noop_cb.t',
80 't/author-pp-13-taint.t',
81 't/author-pp-14-no_validate.t',
82 't/author-pp-15-case.t',
83 't/author-pp-16-normalize.t',
84 't/author-pp-17-callbacks.t',
85 't/author-pp-18-depends.t',
86 't/author-pp-19-untaint.t',
87 't/author-pp-21-can.t',
88 't/author-pp-22-overload-can-bug.t',
89 't/author-pp-23-readonly.t',
90 't/author-pp-24-tied.t',
91 't/author-pp-25-undef-regex.t',
92 't/author-pp-26-isa.t',
93 't/author-pp-27-string-as-type.t',
94 't/author-pp-28-readonly-return.t',
95 't/author-pp-29-taint-mode.t',
96 't/author-pp-30-hashref-alteration.t',
97 't/author-pp-31-incorrect-spelling.t',
98 't/author-pp-32-regex-as-value.t',
99 't/author-pp-33-keep-errsv.t',
100 't/author-pp-34-recursive-validation.t',
101 't/author-pp-35-default-xs-bug.t',
102 't/author-pp-36-large-arrays.t',
103 't/author-pp-37-exports.t',
104 't/author-pp-38-callback-message.t',
105 't/author-pp-39-reentrant.t',
106 't/author-pp-is-loaded.t',
107 't/author-xs-is-loaded.t',
108 't/author-xs-segfault.t',
109 't/author-xs-stack-realloc.t',
68110 't/lib/PVTests.pm',
69111 't/lib/PVTests/Callbacks.pm',
70112 't/lib/PVTests/Defaults.pm',
72114 't/lib/PVTests/Standard.pm',
73115 't/lib/PVTests/With.pm',
74116 't/release-cpan-changes.t',
75 't/release-memory-leak.t',
76117 't/release-meta-json.t',
77118 't/release-pod-coverage.t',
78119 't/release-pod-linkcheck.t',
79120 't/release-pod-no404s.t',
80121 't/release-portability.t',
81 't/release-pp-01-validate.t',
82 't/release-pp-02-noop.t',
83 't/release-pp-04-defaults.t',
84 't/release-pp-05-noop_default.t',
85 't/release-pp-06-options.t',
86 't/release-pp-07-with.t',
87 't/release-pp-08-noop_with.t',
88 't/release-pp-09-regex.t',
89 't/release-pp-10-noop_regex.t',
90 't/release-pp-11-cb.t',
91 't/release-pp-12-noop_cb.t',
92 't/release-pp-13-taint.t',
93 't/release-pp-14-no_validate.t',
94 't/release-pp-15-case.t',
95 't/release-pp-16-normalize.t',
96 't/release-pp-17-callbacks.t',
97 't/release-pp-18-depends.t',
98 't/release-pp-19-untaint.t',
99 't/release-pp-21-can.t',
100 't/release-pp-22-overload-can-bug.t',
101 't/release-pp-23-readonly.t',
102 't/release-pp-24-tied.t',
103 't/release-pp-25-undef-regex.t',
104 't/release-pp-26-isa.t',
105 't/release-pp-27-string-as-type.t',
106 't/release-pp-28-readonly-return.t',
107 't/release-pp-29-taint-mode.t',
108 't/release-pp-30-hashref-alteration.t',
109 't/release-pp-31-incorrect-spelling.t',
110 't/release-pp-32-regex-as-value.t',
111 't/release-pp-33-keep-errsv.t',
112 't/release-pp-34-recursive-validation.t',
113 't/release-pp-35-default-xs-bug.t',
114 't/release-pp-36-large-arrays.t',
115 't/release-pp-37-exports.t',
116 't/release-pp-38-callback-message.t',
117 't/release-pp-39-reentrant.t',
118 't/release-pp-is-loaded.t',
119 't/release-synopsis.t',
120 't/release-xs-is-loaded.t',
121 't/release-xs-segfault.t',
122 't/release-xs-stack-realloc.t'
122 't/release-synopsis.t'
123123 );
124124
125125 eol_unix_ok($_, { trailing_whitespace => 1 }) foreach @files;
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::LeakTrace qw( no_leaks_ok );
12 use Test::More;
13
14 use Params::Validate qw( validate );
15
16 subtest(
17 'callback with default error' => sub {
18 no_leaks_ok( sub { val1( foo => 42 ); }, 'validation passes' );
19 local $TODO = 'Not sure if all the leaks are in Carp or not';
20 no_leaks_ok(
21 sub {
22 eval { val1( foo => 'forty two' ) };
23 },
24 'validation fails'
25 );
26 },
27 );
28
29 subtest(
30 'callback that dies with string' => sub {
31 no_leaks_ok( sub { val2( foo => 42 ); }, 'validation passes' );
32 local $TODO = 'Not sure if all the leaks are in Carp or not';
33 no_leaks_ok(
34 sub {
35 eval { val2( foo => 'forty two' ) };
36 },
37 'validation fails'
38 );
39 },
40 );
41
42 subtest(
43 'callback that dies with object' => sub {
44 no_leaks_ok( sub { val3( foo => 42 ); }, 'validation passes' );
45 no_leaks_ok(
46 sub {
47 eval { val3( foo => 'forty two' ) };
48 },
49 'validation fails'
50 );
51 },
52 );
53
54 done_testing();
55
56 sub val1 {
57 validate(
58 @_,
59 {
60 foo => {
61 callbacks => {
62 'is int' => sub { $_[0] =~ /^[0-9]+$/ }
63 }
64 },
65 },
66 );
67 }
68
69 sub val2 {
70 validate(
71 @_,
72 {
73 foo => {
74 callbacks => {
75 'is int' => sub {
76 $_[0] =~ /^[0-9]+$/ or die "$_[0] is not an integer";
77 }
78 }
79 },
80 },
81 );
82 }
83
84 sub val3 {
85 validate(
86 @_,
87 {
88 foo => {
89 callbacks => {
90 'is int' => sub {
91 $_[0] =~ /^[0-9]+$/
92 or die { error => "$_[0] is not an integer" };
93 }
94 }
95 },
96 },
97 );
98 }
6161 't/39-reentrant.t',
6262 't/author-00-compile.t',
6363 't/author-eol.t',
64 't/author-memory-leak.t',
6465 't/author-mojibake.t',
6566 't/author-no-tabs.t',
6667 't/author-pod-spell.t',
6768 't/author-pod-syntax.t',
69 't/author-pp-01-validate.t',
70 't/author-pp-02-noop.t',
71 't/author-pp-04-defaults.t',
72 't/author-pp-05-noop_default.t',
73 't/author-pp-06-options.t',
74 't/author-pp-07-with.t',
75 't/author-pp-08-noop_with.t',
76 't/author-pp-09-regex.t',
77 't/author-pp-10-noop_regex.t',
78 't/author-pp-11-cb.t',
79 't/author-pp-12-noop_cb.t',
80 't/author-pp-13-taint.t',
81 't/author-pp-14-no_validate.t',
82 't/author-pp-15-case.t',
83 't/author-pp-16-normalize.t',
84 't/author-pp-17-callbacks.t',
85 't/author-pp-18-depends.t',
86 't/author-pp-19-untaint.t',
87 't/author-pp-21-can.t',
88 't/author-pp-22-overload-can-bug.t',
89 't/author-pp-23-readonly.t',
90 't/author-pp-24-tied.t',
91 't/author-pp-25-undef-regex.t',
92 't/author-pp-26-isa.t',
93 't/author-pp-27-string-as-type.t',
94 't/author-pp-28-readonly-return.t',
95 't/author-pp-29-taint-mode.t',
96 't/author-pp-30-hashref-alteration.t',
97 't/author-pp-31-incorrect-spelling.t',
98 't/author-pp-32-regex-as-value.t',
99 't/author-pp-33-keep-errsv.t',
100 't/author-pp-34-recursive-validation.t',
101 't/author-pp-35-default-xs-bug.t',
102 't/author-pp-36-large-arrays.t',
103 't/author-pp-37-exports.t',
104 't/author-pp-38-callback-message.t',
105 't/author-pp-39-reentrant.t',
106 't/author-pp-is-loaded.t',
107 't/author-xs-is-loaded.t',
108 't/author-xs-segfault.t',
109 't/author-xs-stack-realloc.t',
68110 't/lib/PVTests.pm',
69111 't/lib/PVTests/Callbacks.pm',
70112 't/lib/PVTests/Defaults.pm',
72114 't/lib/PVTests/Standard.pm',
73115 't/lib/PVTests/With.pm',
74116 't/release-cpan-changes.t',
75 't/release-memory-leak.t',
76117 't/release-meta-json.t',
77118 't/release-pod-coverage.t',
78119 't/release-pod-linkcheck.t',
79120 't/release-pod-no404s.t',
80121 't/release-portability.t',
81 't/release-pp-01-validate.t',
82 't/release-pp-02-noop.t',
83 't/release-pp-04-defaults.t',
84 't/release-pp-05-noop_default.t',
85 't/release-pp-06-options.t',
86 't/release-pp-07-with.t',
87 't/release-pp-08-noop_with.t',
88 't/release-pp-09-regex.t',
89 't/release-pp-10-noop_regex.t',
90 't/release-pp-11-cb.t',
91 't/release-pp-12-noop_cb.t',
92 't/release-pp-13-taint.t',
93 't/release-pp-14-no_validate.t',
94 't/release-pp-15-case.t',
95 't/release-pp-16-normalize.t',
96 't/release-pp-17-callbacks.t',
97 't/release-pp-18-depends.t',
98 't/release-pp-19-untaint.t',
99 't/release-pp-21-can.t',
100 't/release-pp-22-overload-can-bug.t',
101 't/release-pp-23-readonly.t',
102 't/release-pp-24-tied.t',
103 't/release-pp-25-undef-regex.t',
104 't/release-pp-26-isa.t',
105 't/release-pp-27-string-as-type.t',
106 't/release-pp-28-readonly-return.t',
107 't/release-pp-29-taint-mode.t',
108 't/release-pp-30-hashref-alteration.t',
109 't/release-pp-31-incorrect-spelling.t',
110 't/release-pp-32-regex-as-value.t',
111 't/release-pp-33-keep-errsv.t',
112 't/release-pp-34-recursive-validation.t',
113 't/release-pp-35-default-xs-bug.t',
114 't/release-pp-36-large-arrays.t',
115 't/release-pp-37-exports.t',
116 't/release-pp-38-callback-message.t',
117 't/release-pp-39-reentrant.t',
118 't/release-pp-is-loaded.t',
119 't/release-synopsis.t',
120 't/release-xs-is-loaded.t',
121 't/release-xs-segfault.t',
122 't/release-xs-stack-realloc.t'
122 't/release-synopsis.t'
123123 );
124124
125125 notabs_ok($_) foreach @files;
1717 add_stopwords(<DATA>);
1818 all_pod_files_spelling_ok( qw( bin lib ) );
1919 __DATA__
20 drolsky
2021 DROLSKY
2122 DROLSKY's
2223 PayPal
4950 Olivier
5051 Mengué
5152 dolmen
53 Tony
54 Cook
55 tony
5256 Vincent
5357 Pit
5458 perl
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Standard;
19 PVTests::Standard::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Standard;
21 PVTests::Standard::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Defaults;
19 PVTests::Defaults::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Defaults;
21 PVTests::Defaults::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests;
19 use Test::More;
20
21 use Params::Validate qw(:all);
22
23 validation_options( stack_skip => 2 );
24
25 sub foo {
26 my %p = validate( @_, { bar => 1 } );
27 }
28
29 sub bar { foo(@_) }
30
31 sub baz { bar(@_) }
32
33 eval { baz() };
34
35 like( $@, qr/mandatory.*missing.*call to main::bar/i );
36
37 validation_options( stack_skip => 3 );
38
39 eval { baz() };
40 like( $@, qr/mandatory.*missing.*call to main::baz/i );
41
42 validation_options( on_fail => sub { die bless { hash => 'ref' }, 'Dead' } );
43
44 eval { baz() };
45
46 my $e = $@;
47 is( $e->{hash}, 'ref' );
48 ok( eval { $e->isa('Dead'); 1; } );
49
50 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::With;
19 PVTests::With::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::With;
21 PVTests::With::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Regex;
19 PVTests::Regex::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Regex;
21 PVTests::Regex::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Callbacks;
19 PVTests::Callbacks::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Callbacks;
21 PVTests::Callbacks::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 eval { "$0$^X" && kill 0; 1 };
19
20 use PVTests::Standard;
21 PVTests::Standard::run_tests();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use lib './t';
16
17 use Params::Validate qw(validate);
18
19 use Test::More;
20 plan tests => $] == 5.006 ? 2 : 3;
21
22 eval { foo() };
23 like( $@, qr/parameter 'foo'/ );
24
25 {
26 local $Params::Validate::NO_VALIDATION = 1;
27
28 eval { foo() };
29 is( $@, q{} );
30 }
31
32 unless ( $] == 5.006 ) {
33 eval { foo() };
34 like( $@, qr/parameter 'foo'/ );
35 }
36
37 sub foo {
38 validate( @_, { foo => 1 } );
39 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More;
16
17 use Params::Validate qw(validate validate_with);
18
19 my @testset;
20
21 # Generate test cases ...
22 BEGIN {
23 my @lower_case_args = ( foo => 1 );
24 my @upper_case_args = ( FOO => 1 );
25 my @mixed_case_args = ( FoO => 1 );
26
27 my %lower_case_spec = ( foo => 1 );
28 my %upper_case_spec = ( FOO => 1 );
29 my %mixed_case_spec = ( FoO => 1 );
30
31 my %arglist = (
32 lower => \@lower_case_args,
33 upper => \@upper_case_args,
34 mixed => \@mixed_case_args
35 );
36
37 my %speclist = (
38 lower => \%lower_case_spec,
39 upper => \%upper_case_spec,
40 mixed => \%mixed_case_spec
41 );
42
43 # XXX - make subs such that user gets to see the error message
44 # when a test fails
45 my $ok_sub = sub {
46 if ($@) {
47 print STDERR $@;
48 }
49 !$@;
50 };
51
52 my $nok_sub = sub {
53 my $ok = ( $@ =~ /not listed in the validation options/ );
54 unless ($ok) {
55 print STDERR $@;
56 }
57 $ok;
58 };
59
60 # generate testcases on the fly (I'm too lazy)
61 for my $ignore_case (qw( 0 1 )) {
62 for my $args ( keys %arglist ) {
63 for my $spec ( keys %speclist ) {
64 push @testset, {
65 params => $arglist{$args},
66 spec => $speclist{$spec},
67 expect => (
68 $ignore_case ? $ok_sub
69 : $args eq $spec ? $ok_sub
70 : $nok_sub
71 ),
72 ignore_case => $ignore_case
73 };
74 }
75 }
76 }
77 }
78
79 plan tests => ( scalar @testset ) * 2;
80
81 {
82
83 # XXX - "called" will be all messed up, but what the heck
84 foreach my $case (@testset) {
85 my %args = eval {
86 validate_with(
87 params => $case->{params},
88 spec => $case->{spec},
89 ignore_case => $case->{ignore_case}
90 );
91 };
92
93 ok( $case->{expect}->(%args) );
94 }
95
96 # XXX - make sure that it works from validation_options() as well
97 foreach my $case (@testset) {
98 Params::Validate::validation_options(
99 ignore_case => $case->{ignore_case} );
100
101 my %args = eval {
102 my @args = @{ $case->{params} };
103 validate( @args, $case->{spec} );
104 };
105
106 ok( $case->{expect}->(%args) );
107 }
108 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_with);
16 use Test::More;
17
18 my $ucfirst_normalizer = sub { return ucfirst lc $_[0] };
19
20 sub sub1 {
21 my %args = validate_with(
22 params => \@_,
23 spec => { PaRaMkEy => 1 },
24 normalize_keys => $ucfirst_normalizer
25 );
26
27 return $args{Paramkey};
28 }
29
30 sub sub2 {
31
32 # verify that normalize_callback surpresses ignore_case
33 my %args = validate_with(
34 params => \@_,
35 spec => { PaRaMkEy => 1 },
36 normalize_keys => $ucfirst_normalizer,
37 ignore_case => 1
38 );
39
40 return $args{Paramkey};
41 }
42
43 sub sub3 {
44
45 # verify that normalize_callback surpresses strip_leading
46 my %args = validate_with(
47 params => \@_,
48 spec => { -PaRaMkEy => 1 },
49 normalize_keys => $ucfirst_normalizer,
50 strip_leading => '-'
51 );
52
53 return $args{-paramkey};
54 }
55
56 sub sub4 {
57 my %args = validate_with(
58 params => \@_,
59 spec => { foo => 1 },
60 normalize_keys => sub {undef}
61 );
62 }
63
64 sub sub5 {
65 my %args = validate_with(
66 params => \@_,
67 spec => { foo => 1 },
68 normalize_keys => sub { return 'a' },
69 );
70 }
71
72 ok( eval { sub1( pArAmKeY => 1 ) } );
73 ok( eval { sub2( pArAmKeY => 1 ) } );
74 ok( eval { sub3( -pArAmKeY => 1 ) } );
75
76 eval { sub4( foo => 5 ) };
77 like( $@, qr/normalize_keys.+a defined value/ );
78
79 eval { sub5( foo => 5, bar => 5 ) };
80 like( $@, qr/normalize_keys.+already exists/ );
81
82 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_pos SCALAR);
16 use Test::More;
17
18 {
19 my @p = ( foo => 1, bar => 2 );
20
21 eval {
22 validate(
23 @p, {
24 foo => {
25 type => SCALAR,
26 callbacks => {
27 'bigger than bar' => sub { $_[0] > $_[1]->{bar} }
28 },
29 },
30 bar => { type => SCALAR },
31 }
32 );
33 };
34
35 like( $@, qr/bigger than bar/ );
36
37 $p[1] = 3;
38 eval {
39 validate(
40 @p, {
41 foo => {
42 type => SCALAR,
43 callbacks => {
44 'bigger than bar' => sub { $_[0] > $_[1]->{bar} }
45 },
46 },
47 bar => { type => SCALAR },
48 }
49 );
50 };
51
52 is( $@, q{} );
53 }
54
55 {
56 my @p = ( 1, 2, 3 );
57 eval {
58 validate_pos(
59 @p, {
60 type => SCALAR,
61 callbacks => {
62 'bigger than [1]' => sub { $_[0] > $_[1]->[1] }
63 }
64 },
65 { type => SCALAR },
66 { type => SCALAR },
67 );
68 };
69
70 like( $@, qr/bigger than \[1\]/ );
71
72 $p[0] = 5;
73 eval {
74 validate_pos(
75 @p, {
76 type => SCALAR,
77 callbacks => {
78 'bigger than [1]' => sub { $_[0] > $_[1]->[1] }
79 }
80 },
81 { type => SCALAR },
82 { type => SCALAR },
83 );
84 };
85
86 is( $@, q{} );
87 }
88
89 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_pos);
16 use Test::More;
17
18 {
19 my %spec = (
20 foo => { optional => 1, depends => 'bar' },
21 bar => { optional => 1 },
22 );
23
24 my @args = ( bar => 1 );
25
26 eval { validate( @args, \%spec ) };
27
28 is( $@, q{}, "validate() single depends(1): no depends, positive" );
29
30 @args = ( foo => 1, bar => 1 );
31 eval { validate( @args, \%spec ) };
32
33 is( $@, q{}, "validate() single depends(2): with depends, positive" );
34
35 @args = ( foo => 1 );
36 eval { validate( @args, \%spec ) };
37
38 ok( $@, "validate() single depends(3.a): with depends, negative" );
39 like(
40 $@,
41 qr(^Parameter 'foo' depends on parameter 'bar', which was not given),
42 "validate() single depends(3.b): check error string"
43 );
44 }
45
46 {
47 my %spec = (
48 foo => { optional => 1, depends => [qw(bar baz)] },
49 bar => { optional => 1 },
50 baz => { optional => 1 },
51 );
52
53 # positive, no depends (single, multiple)
54 my @args = ( bar => 1 );
55 eval { validate( @args, \%spec ) };
56 is(
57 $@, q{},
58 "validate() multiple depends(1): no depends, single arg, positive"
59 );
60
61 @args = ( bar => 1, baz => 1 );
62 eval { validate( @args, \%spec ) };
63
64 is(
65 $@, q{},
66 "validate() multiple depends(2): no depends, multiple arg, positive"
67 );
68
69 @args = ( foo => 1, bar => 1, baz => 1 );
70 eval { validate( @args, \%spec ) };
71
72 is( $@, q{}, "validate() multiple depends(3): with depends, positive" );
73
74 @args = ( foo => 1, bar => 1 );
75 eval { validate( @args, \%spec ) };
76
77 ok(
78 $@,
79 "validate() multiple depends(4.a): with depends, negative, multiple missing"
80 );
81 like(
82 $@,
83 qr(^Parameter 'foo' depends on parameter 'baz', which was not given),
84 "validate() multiple depends (4.b): check error string"
85 );
86
87 @args = ( foo => 1 );
88 eval { validate( @args, \%spec ) };
89
90 ok(
91 $@,
92 "validate() multiple depends(5.a): with depends, negative, multiple missing"
93 );
94 like(
95 $@,
96 qr(^Parameter 'foo' depends on parameter '(bar|baz)', which was not given),
97 "validate() multiple depends (5.b): check error string"
98 );
99 }
100
101 {
102
103 # bad depends
104 my %spec = (
105 foo => { optional => 1, depends => { 'bar' => 1 } },
106 bar => { optional => 1 },
107 );
108
109 my @args = ( foo => 1 );
110 eval { validate( @args, \%spec ) };
111
112 ok( $@, "validate() bad depends spec (1.a): depends is a hashref" );
113 like(
114 $@,
115 qr(^Arguments to 'depends' must be a scalar or arrayref),
116 "validate() bad depends spec (1.a): check error string"
117 );
118 }
119
120 {
121 my @spec = ( { optional => 1 } );
122
123 my @args = qw(1);
124 eval { validate_pos( @args, @spec ) };
125
126 is( $@, q{}, "validate_pos() no depends, positive" );
127 }
128
129 {
130 my @spec = ( { optional => 1, depends => 2 }, { optional => 1 } );
131
132 my @args = qw(1 1);
133 eval { validate_pos( @args, @spec ) };
134
135 is(
136 $@, q{},
137 "validate_pos() single depends (1): with depends, positive"
138 );
139 }
140
141 {
142 my @spec = (
143 { optional => 1, depends => 4 },
144 { optional => 1 }, { optional => 1 },
145 { optional => 1 }
146 );
147
148 my @args = qw(1 0);
149 eval { validate_pos( @args, @spec ) };
150
151 ok( $@, "validate_pos() single depends (2.a): with depends, negative" );
152 like(
153 $@,
154 qr(^Parameter #1 depends on parameter #4, which was not given),
155 "validate_pos() single depends (2.b): check error"
156 );
157 }
158
159 {
160 my @spec = (
161 { optional => 1, depends => [ 2, 3 ] },
162 { optional => 1 },
163 0
164 );
165 my @args = qw(1);
166 eval { validate_pos( @args, @spec ) };
167
168 ok(
169 $@,
170 "validate_pos() multiple depends (1.a): with depends, bad args negative"
171 );
172 like(
173 $@,
174 qr{^Arguments to 'depends' for validate_pos\(\) must be a scalar},
175 "validate_pos() multiple depends (1.b): check error"
176 );
177 }
178
179 done_testing();
0 #!/usr/bin/perl -T
1
2 BEGIN {
3 unless ($ENV{AUTHOR_TESTING}) {
4 require Test::More;
5 Test::More::plan(skip_all => 'these tests are for testing by the author');
6 }
7 }
8
9
10 BEGIN {
11 $ENV{PV_TEST_PERL} = 1;
12 }
13
14
15 use strict;
16 use warnings;
17
18 use Test::Requires {
19 'Test::Taint' => 0.02,
20 };
21
22 use Params::Validate qw(validate validate_pos);
23 use Test::More;
24
25 taint_checking_ok('These tests are meaningless unless we are in taint mode.');
26
27 {
28 my $value = 7;
29 taint($value);
30
31 tainted_ok( $value, 'make sure $value is tainted' );
32
33 my @p = ( value => $value );
34 my %p = validate(
35 @p, {
36 value => {
37 regex => qr/^\d+$/,
38 untaint => 1,
39 },
40 },
41 );
42
43 untainted_ok( $p{value}, 'value is untainted after validation' );
44 }
45
46 {
47 my $value = 'foo';
48
49 taint($value);
50
51 tainted_ok( $value, 'make sure $value is tainted' );
52
53 my @p = ($value);
54 my ($new_value) = validate_pos(
55 @p, {
56 regex => qr/foo/,
57 untaint => 1,
58 },
59 );
60
61 untainted_ok( $new_value, 'value is untainted after validation' );
62 }
63
64 {
65 my $value = 7;
66 taint($value);
67
68 tainted_ok( $value, 'make sure $value is tainted' );
69
70 my @p = ( value => $value );
71 my %p = validate(
72 @p, {
73 value => {
74 regex => qr/^\d+$/,
75 },
76 },
77 );
78
79 tainted_ok( $p{value}, 'value is still tainted after validation' );
80 }
81
82 {
83 my $value = 'foo';
84
85 taint($value);
86
87 tainted_ok( $value, 'make sure $value is tainted' );
88
89 my @p = ($value);
90 my ($new_value) = validate_pos(
91 @p, {
92 regex => qr/foo/,
93 },
94 );
95
96 tainted_ok( $new_value, 'value is still tainted after validation' );
97 }
98
99 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @p = ( foo => 'ClassCan' );
20
21 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
22
23 is( $@, q{} );
24
25 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
26
27 like( $@, qr/does not have the method: 'thingy'/ );
28 }
29
30 {
31 my @p = ( foo => undef );
32 eval { validate( @p, { foo => { can => 'baz' } }, ); };
33
34 like( $@, qr/does not have the method: 'baz'/ );
35 }
36
37 {
38 my $object = bless {}, 'ClassCan';
39 my @p = ( foo => $object );
40
41 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
42
43 is( $@, q{} );
44
45 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
46
47 like( $@, qr/does not have the method: 'thingy'/ );
48 }
49
50 {
51 my @p = ( foo => 'SubClass' );
52
53 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
54
55 is( $@, q{}, 'SubClass->can(cancan)' );
56
57 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
58
59 like( $@, qr/does not have the method: 'thingy'/ );
60 }
61
62 {
63 my $object = bless {}, 'SubClass';
64 my @p = ( foo => $object );
65
66 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
67
68 is( $@, q{}, 'SubClass object->can(cancan)' );
69
70 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
71
72 like( $@, qr/does not have the method: 'thingy'/ );
73 }
74
75 {
76 my @p = ( foo => {} );
77 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
78 like( $@, qr/does not have the method: 'thingy'/, 'unblessed ref ->can' );
79
80 @p = ( foo => 27 );
81 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
82 like( $@, qr/does not have the method: 'thingy'/, 'number can' );
83
84 @p = ( foo => 'A String' );
85 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
86 like( $@, qr/does not have the method: 'thingy'/, 'string can' );
87
88 @p = ( foo => undef );
89 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
90 like( $@, qr/does not have the method: 'thingy'/, 'undef can' );
91 }
92
93 done_testing();
94
95 package ClassCan;
96
97 sub can {
98 return 1 if $_[1] eq 'cancan';
99 return 0;
100 }
101
102 sub thingy {1}
103
104 package SubClass;
105
106 use base 'ClassCan';
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 package Overloaded;
20
21 use overload 'bool' => sub {0};
22
23 sub new { bless {} }
24
25 sub foo {1}
26 }
27
28 my $ovl = Overloaded->new;
29
30 {
31 eval {
32 my @p = ( object => $ovl );
33 validate( @p, { object => { isa => 'Overloaded' } } );
34 };
35
36 is( $@, q{}, 'overloaded object->isa' );
37 }
38
39 {
40 eval {
41 my @p = ( object => $ovl );
42 validate( @p, { object => { can => 'foo' } } );
43 };
44
45 is( $@, q{}, 'overloaded object->foo' );
46 }
47
48 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::Requires {
16 Readonly => '1.03',
17 'Scalar::Util' => '1.20',
18 };
19
20 use Params::Validate qw(validate validate_pos SCALAR);
21 use Test::More;
22
23 plan skip_all => 'These tests fail with Readonly 1.50 for some reason'
24 if Readonly::->VERSION() =~ /^v?1.5/;
25
26 {
27 Readonly my $spec => { foo => 1 };
28 my @p = ( foo => 'hello' );
29
30 eval { validate( @p, $spec ) };
31 is( $@, q{}, 'validate() call succeeded with Readonly spec hashref' );
32 }
33
34 {
35 Readonly my $spec => { type => SCALAR };
36 my @p = 'hello';
37
38 eval { validate_pos( @p, $spec ) };
39 is( $@, q{}, 'validate_pos() call succeeded with Readonly spec hashref' );
40 }
41
42 {
43 Readonly my %spec => ( foo => { type => SCALAR } );
44 my @p = ( foo => 'hello' );
45
46 eval { validate( @p, \%spec ) };
47 is( $@, q{}, 'validate() call succeeded with Readonly spec hash' );
48 }
49
50 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_pos SCALAR);
16 use Test::More;
17
18 {
19 package Tie::SimpleArray;
20 use Tie::Array;
21 use base 'Tie::StdArray';
22 }
23
24 {
25
26 package Tie::SimpleHash;
27 use Tie::Hash;
28 use base 'Tie::StdHash';
29 }
30
31 {
32 tie my @p, 'Tie::SimpleArray';
33
34 my %spec = ( foo => 1 );
35 push @p, ( foo => 'hello' );
36
37 eval { validate( @p, \%spec ) };
38 warn $@ if $@;
39 is(
40 $@, q{},
41 'validate() call succeeded with tied params array and regular hashref spec'
42 );
43 }
44
45 SKIP:
46 {
47 skip 'Params::Validate segfaults with tied hash for spec', 1;
48
49 my @p;
50 tie my %spec, 'Tie::SimpleHash';
51
52 $spec{foo} = 1;
53 push @p, ( foo => 'hello' );
54
55 eval { validate( @p, \%spec ) };
56 warn $@ if $@;
57 is(
58 $@, q{},
59 'validate() call succeeded with regular params array and tied hashref spec'
60 );
61 }
62
63 SKIP:
64 {
65 skip 'Params::Validate segfaults with tied hash for spec', 1;
66
67 tie my @p, 'Tie::SimpleArray';
68 tie my %spec, 'Tie::SimpleHash';
69
70 $spec{foo} = 1;
71 push @p, ( foo => 'hello' );
72
73 eval { validate( @p, \%spec ) };
74 warn $@ if $@;
75 is(
76 $@, q{},
77 'validate() call succeeded with tied params array and tied hashref spec'
78 );
79 }
80
81 {
82 tie my @p, 'Tie::SimpleArray';
83 my %spec;
84
85 $spec{type} = SCALAR;
86 push @p, 'hello';
87
88 eval { validate_pos( @p, \%spec ) };
89 warn $@ if $@;
90 is(
91 $@, q{},
92 'validate_pos() call succeeded with tied params array and regular hashref spec'
93 );
94 }
95
96 SKIP:
97 {
98 skip 'Params::Validate segfaults with tied hash for spec', 1;
99
100 my @p;
101 tie my %spec, 'Tie::SimpleHash';
102
103 $spec{type} = SCALAR;
104 push @p, 'hello';
105
106 eval { validate_pos( @p, \%spec ) };
107 warn $@ if $@;
108 is(
109 $@, q{},
110 'validate_pos() call succeeded with regular params array and tied hashref spec'
111 );
112 }
113
114 SKIP:
115 {
116 skip 'Params::Validate segfaults with tied hash for spec', 1;
117
118 tie my @p, 'Tie::SimpleArray';
119 tie my %spec, 'Tie::SimpleHash';
120
121 $spec{type} = SCALAR;
122 push @p, 'hello';
123
124 eval { validate_pos( @p, \%spec ) };
125 warn $@ if $@;
126 is(
127 $@, q{},
128 'validate_pos() call succeeded with tied params array and tied hashref spec'
129 );
130 }
131
132 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @w;
20 local $SIG{__WARN__} = sub { push @w, @_ };
21
22 my @p = ( foo => undef );
23 eval { validate( @p, { foo => { regex => qr/^bar/ } } ) };
24 ok( $@, 'validation failed' );
25 ok( !@w, 'no warnings' );
26 }
27
28 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @p = ( foo => 'ClassISA' );
20
21 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
22
23 is( $@, q{}, 'no error checking if ClassISA->isa(FooBar)' );
24
25 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
26
27 like( $@, qr/was not a 'Thingy'/ );
28 }
29
30 {
31 my @p = ( foo => undef );
32 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
33
34 like( $@, qr/was not a 'FooBar'/ );
35 }
36
37 {
38 my @p = ( foo => 'SubClass' );
39
40 eval { validate( @p, { foo => { isa => 'ClassISA' } }, ); };
41
42 is( $@, q{}, 'SubClass->isa(ClassISA)' );
43
44 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
45
46 is( $@, q{}, 'SubClass->isa(FooBar)' );
47
48 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
49
50 like( $@, qr/was not a 'Thingy'/ );
51 }
52
53 {
54 my @p = ( foo => bless {}, 'SubClass' );
55
56 eval { validate( @p, { foo => { isa => 'ClassISA' } }, ); };
57
58 is( $@, q{}, 'SubClass->isa(ClassISA)' );
59
60 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
61
62 is( $@, q{}, 'SubClass->isa(FooBar)' );
63
64 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
65
66 like( $@, qr/was not a 'Thingy'/ );
67 }
68
69 {
70 my @p = ( foo => {} );
71 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
72 like( $@, qr/was not a 'Thingy'/, 'unblessed ref ->isa' );
73
74 @p = ( foo => 27 );
75 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
76 like( $@, qr/was not a 'Thingy'/, 'number isa' );
77
78 @p = ( foo => 'A String' );
79 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
80 like( $@, qr/was not a 'Thingy'/, 'string isa' );
81
82 @p = ( foo => undef );
83 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
84 like( $@, qr/was not a 'Thingy'/, 'undef isa' );
85 }
86
87 done_testing();
88
89 package ClassISA;
90
91 sub isa {
92 return 1 if $_[1] eq 'FooBar';
93 return $_[0]->SUPER::isa( $_[1] );
94 }
95
96 sub thingy {1}
97
98 package SubClass;
99
100 use base 'ClassISA';
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @p = ( foo => 1 );
20
21 eval { validate( @p, { foo => { type => 'SCALAR' } }, ); };
22
23 like(
24 $@,
25 qr/\QThe 'foo' parameter ("1") has a type specification which is not a number. It is a string - SCALAR/
26 );
27 }
28
29 {
30 my @p = ( foo => 1 );
31
32 eval { validate( @p, { foo => { type => undef } }, ); };
33
34 like(
35 $@,
36 qr/\QThe 'foo' parameter ("1") has a type specification which is not a number. It is undef/
37 );
38
39 }
40
41 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14 use Test::More;
15
16 use Devel::Peek qw( SvREFCNT );
17 use File::Temp qw( tempfile );
18 use Params::Validate qw( validate SCALAR HANDLE );
19
20 {
21 my $fh = tempfile();
22 my @p = (
23 foo => 1,
24 bar => $fh,
25 );
26
27 my $ref = val1(@p);
28
29 eval { $ref->{foo} = 2 };
30 ok( !$@, 'returned hashref values are not read only' );
31 is( $ref->{foo}, 2, 'double check that setting value worked' );
32 is( $fh, $ref->{bar}, 'filehandle is not copied during validation' );
33 }
34
35 {
36
37 package ScopeTest;
38
39 my $live = 0;
40
41 sub new { $live++; bless {}, shift }
42 sub DESTROY { $live-- }
43
44 sub Live {$live}
45 }
46
47 {
48 my @p = ( foo => ScopeTest->new() );
49
50 is(
51 ScopeTest->Live(), 1,
52 'one live object'
53 );
54
55 my $ref = val2(@p);
56
57 isa_ok( $ref->{foo}, 'ScopeTest' );
58
59 @p = ();
60
61 is(
62 ScopeTest->Live(), 1,
63 'still one live object'
64 );
65
66 ok(
67 defined $ref->{foo},
68 'foo key stays in scope after original version goes out of scope'
69 );
70 is(
71 SvREFCNT( $ref->{foo} ), 1,
72 'ref count for reference is 1'
73 );
74
75 undef $ref->{foo};
76
77 is(
78 ScopeTest->Live(), 0,
79 'no live objects'
80 );
81 }
82
83 sub val1 {
84 my $ref = validate(
85 @_, {
86 foo => { type => SCALAR },
87 bar => { type => HANDLE, optional => 1 },
88 },
89 );
90
91 return $ref;
92 }
93
94 sub val2 {
95 my $ref = validate(
96 @_, {
97 foo => 1,
98 },
99 );
100
101 return $ref;
102 }
103
104 done_testing();
0 #!perl -T
1
2 BEGIN {
3 unless ($ENV{AUTHOR_TESTING}) {
4 require Test::More;
5 Test::More::plan(skip_all => 'these tests are for testing by the author');
6 }
7 }
8
9
10 BEGIN {
11 $ENV{PV_TEST_PERL} = 1;
12 }
13
14
15 use strict;
16 use warnings;
17
18 use Test::Requires {
19 'Test::Taint' => 0.02,
20 };
21
22 use Test::Fatal;
23 use Test::More;
24
25 use Params::Validate qw( validate validate_pos ARRAYREF );
26
27 taint_checking_ok('These tests are meaningless unless we are in taint mode.');
28
29 sub test1 {
30 my $def = $0;
31 tainted_ok( $def, 'make sure $def is tainted' );
32
33 # The spec is irrelevant, all that matters is that there's a
34 # tainted scalar as the default
35 my %p = validate( @_, { foo => { default => $def } } );
36 }
37
38 {
39 is(
40 exception { test1() },
41 undef,
42 'no taint error when we validate with tainted default value'
43 );
44 }
45
46 sub test2 {
47 return validate_pos( @_, { regex => qr/^b/ } );
48 }
49
50 SKIP:
51 {
52 skip 'This test only passes on Perl 5.14+', 1
53 unless $] >= 5.014;
54
55 my @p = 'cat';
56 taint(@p);
57
58 like(
59 exception { test2(@p) },
60 qr/\QParameter #1 ("cat") to main::test2 did not pass regex check/,
61 'no taint error when we validate with tainted value values being validated'
62 );
63 }
64
65 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14 use Test::More;
15
16 use Params::Validate qw( validate SCALAR );
17
18 {
19 my $p = { foo => 1 };
20
21 val($p);
22
23 is_deeply(
24 $p, { foo => 1 },
25 'validate does not alter hashref passed to val'
26 );
27
28 val2($p);
29
30 is_deeply(
31 $p, { foo => 1 },
32 'validate does not alter hashref passed to val, even with defaults being supplied'
33 );
34 }
35
36 sub val {
37 validate(
38 @_, {
39 foo => { optional => 1 },
40 bar => { optional => 1 },
41 baz => { optional => 1 },
42 buz => { optional => 1 },
43 },
44 );
45
46 return;
47 }
48
49 sub val2 {
50 validate(
51 @_, {
52 foo => { optional => 1 },
53 bar => { default => 42 },
54 baz => { optional => 1 },
55 buz => { optional => 1 },
56 },
57 );
58
59 return;
60 }
61
62 done_testing();
0 #!/usr/bin/perl -w
1
2 BEGIN {
3 unless ($ENV{AUTHOR_TESTING}) {
4 require Test::More;
5 Test::More::plan(skip_all => 'these tests are for testing by the author');
6 }
7 }
8
9
10 BEGIN {
11 $ENV{PV_TEST_PERL} = 1;
12 }
13
14
15 use strict;
16 use warnings;
17
18 use Test::More;
19
20 use Params::Validate qw( validate validate_pos SCALAR );
21
22 plan skip_all => 'Spec validation is disabled for now';
23
24 {
25 my @p = ( foo => 1, bar => 2 );
26
27 eval {
28 validate(
29 @p, {
30 foo => {
31 type => SCALAR,
32 callbucks => {
33 'one' => sub {1}
34 },
35 },
36 bar => { type => SCALAR },
37 }
38 );
39 };
40
41 like( $@, qr/is not an allowed validation spec key/ );
42
43 eval {
44 validate(
45 @p, {
46 foo => {
47 hype => SCALAR,
48 callbacks => {
49 'one' => sub {1}
50 },
51 },
52 bar => { type => SCALAR },
53 }
54 );
55 };
56
57 like( $@, qr/is not an allowed validation spec key/ );
58 eval {
59 validate(
60 @p, {
61 foo => {
62 type => SCALAR,
63 regexp => qr/^\d+$/,
64 },
65 bar => { type => SCALAR },
66 }
67 );
68 };
69
70 like( $@, qr/is not an allowed validation spec key/ );
71 }
72
73 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw( validate SCALAR SCALARREF );
16
17 use Test::More;
18 use Test::Fatal;
19
20 is(
21 exception { v( foo => qr/foo/ ) },
22 undef,
23 'no exception with regex object'
24 );
25
26 is(
27 exception { v( foo => 'foo' ) },
28 undef,
29 'no exception with plain scalar'
30 );
31
32 my $foo = 'foo';
33 is(
34 exception { v( foo => \$foo ) },
35 undef,
36 'no exception with scalar ref'
37 );
38
39 done_testing();
40
41 sub v {
42 validate(
43 @_, {
44 foo => { type => SCALAR | SCALARREF },
45 },
46 );
47 return;
48 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw( validate SCALAR );
16
17 use Test::More;
18
19 {
20 $@ = 'foo';
21 v( bar => 42 );
22
23 is(
24 $@,
25 'foo',
26 'calling validate() does not clobber'
27 );
28 }
29
30 done_testing();
31
32 sub v {
33 validate( @_, { bar => { type => SCALAR } } );
34 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::Fatal;
16 use Test::More;
17
18 {
19 package Foo;
20
21 use Params::Validate qw( validate SCALAR );
22
23 Params::Validate::validation_options( allow_extra => 1 );
24
25 sub test_foo {
26 my %p = validate( @_, { arg1 => { type => SCALAR } } );
27 print "test foo\n";
28 }
29 }
30
31 {
32 package Bar;
33
34 use Params::Validate qw( validate SCALAR );
35 Params::Validate::validation_options( allow_extra => 0 );
36
37 sub test_bar {
38
39 # catch die signal
40 local $SIG{__DIE__} = sub {
41
42 # we died from within Params::Validate (because of wrong_Arg) we
43 # call Foo::test_foo with OK args, but it'll die, because
44 # Params::Validate::PP::options is still set to the options of the
45 # Bar package, and so it won't retreive the one from Foo.
46 Foo::test_foo( arg1 => 1, extra_arg => 2 );
47 };
48
49 # this will die because the arg received is 'wrong_arg'
50 my %p = validate( @_, { arg1 => { type => SCALAR } } );
51 }
52 }
53
54 {
55 # This bug only manifests with the pure Perl code because of its use of local
56 # to remember the per-package options.
57 local $TODO = 'Not sure how to fix this one';
58 unlike(
59 exception { Bar::test_bar( bad_arg => 2 ) },
60 qr/was passed in the call to Foo::test_foo/,
61 'no exception from Foo::test_foo when when calling validate() from within a __DIE__ handler'
62 );
63 }
64
65 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More 0.88;
16
17 use Params::Validate qw( :all );
18
19 default_test();
20
21 done_testing();
22
23 sub default_test {
24 my ( $first, $second ) = validate_pos(
25 @_,
26 { type => SCALAR, optional => 1 },
27 { type => SCALAR, optional => 1, default => 'must be second one' },
28 );
29
30 is( $first, undef, 'no default for first parameter' );
31 is( $second, 'must be second one',
32 'default for second parameter is applied' );
33 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::Fatal;
16 use Test::More;
17
18 {
19 package Foo;
20
21 use Params::Validate qw( validate ARRAYREF );
22
23 sub v1 {
24 my %p = validate(
25 @_, {
26 array => {
27 callbacks => {
28 'checking array contents' => sub {
29 for my $x ( @{ $_[0] } ) {
30 return 0 unless defined $x && !ref $x;
31 }
32 return 1;
33 },
34 }
35 }
36 }
37 );
38 return $p{array};
39 }
40 }
41
42 {
43 for my $size ( 100, 1_000, 100_000 ) {
44 my @array = ('x') x $size;
45 is_deeply(
46 Foo::v1( array => \@array ),
47 \@array,
48 "validate() handles $size element array correctly"
49 );
50 }
51 }
52
53 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More;
16 use Params::Validate ();
17
18 my @types = qw(
19 SCALAR
20 ARRAYREF
21 HASHREF
22 CODEREF
23 GLOB
24 GLOBREF
25 SCALARREF
26 HANDLE
27 BOOLEAN
28 UNDEF
29 OBJECT
30 );
31
32 my @subs = qw(
33 validate
34 validate_pos
35 validation_options
36 validate_with
37 );
38
39 is_deeply(
40 [ sort @Params::Validate::EXPORT_OK ],
41 [ sort @types, @subs, 'set_options' ],
42 '@EXPORT_OK'
43 );
44
45 is_deeply(
46 [ sort keys %Params::Validate::EXPORT_TAGS ],
47 [qw( all types )],
48 'keys %EXPORT_TAGS'
49 );
50
51 is_deeply(
52 [ sort @{ $Params::Validate::EXPORT_TAGS{all} } ],
53 [ sort @types, @subs ],
54 '$EXPORT_TAGS{all}',
55 );
56
57 is_deeply(
58 [ sort @{ $Params::Validate::EXPORT_TAGS{types} } ],
59 [ sort @types ],
60 '$EXPORT_TAGS{types}',
61 );
62
63 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More;
16 use Params::Validate qw( validate );
17
18 {
19 my $e = _test_args(
20 pos_int => 42,
21 string => 'foo',
22 );
23 is(
24 $e,
25 q{},
26 'no error with good args'
27 );
28 }
29
30 {
31 my $e = _test_args(
32 pos_int => 42,
33 string => [],
34 );
35 like(
36 $e,
37 qr/The 'string' parameter \("ARRAY\(.+\)"\) to main::validate1 did not pass the 'string' callback: ARRAY\(.+\) is not a string/,
38 'got error for bad string'
39 );
40 }
41
42 {
43 my $e = _test_args(
44 pos_int => 0,
45 string => 'foo',
46 );
47 like(
48 $e,
49 qr/\QThe 'pos_int' parameter ("0") to main::validate1 did not pass the 'pos_int' callback: 0 is not a positive integer/,
50 'got error for bad pos int (0)'
51 );
52 }
53
54 {
55 my $e = _test_args(
56 pos_int => 'bar',
57 string => 'foo',
58 );
59 like(
60 $e,
61 qr/\QThe 'pos_int' parameter ("bar") to main::validate1 did not pass the 'pos_int' callback: bar is not a positive integer/,
62 'got error for bad pos int (bar)'
63 );
64 }
65
66 {
67 my $e = do {
68 local $@;
69 eval { validate2( string => [] ); };
70 $@;
71 };
72
73 is_deeply(
74 $e,
75 { error => 'not a string' },
76 'ref thrown by callback is preserved, not stringified'
77 );
78 }
79
80 {
81 my $e = do {
82 local $@;
83 eval { validate3( string => [] ); };
84 $@;
85 };
86
87 like(
88 $e,
89 qr/\QThe 'string' parameter (\E.+?\Q) to main::validate3 did not pass the 'string' callback: Died at \E.+/,
90 'callback that dies with an empty string generates a sane error message'
91 );
92 }
93
94 {
95 my $e = do {
96 local $@;
97 eval { validate4( string => [] ); };
98 $@;
99 };
100
101 like(
102 $e,
103 qr/\QThe 'string' parameter (\E.+?\Q) to main::validate4 did not pass the 'string' callback/,
104 'callback that does not dies generates a sane error message'
105 );
106 }
107
108 sub _test_args {
109 local $@;
110 eval { validate1(@_) };
111 return $@;
112 }
113
114 sub validate1 {
115 validate(
116 @_, {
117 pos_int => {
118 callbacks => {
119 pos_int => sub {
120 $_[0] =~ /^[1-9][0-9]*$/
121 or die "$_[0] is not a positive integer\n";
122 },
123 },
124 },
125 string => {
126 callbacks => {
127 string => sub {
128 ( defined $_[0] && !ref $_[0] && length $_[0] )
129 or die "$_[0] is not a string\n";
130 },
131 },
132 },
133 }
134 );
135 }
136
137 sub validate2 {
138 validate(
139 @_, {
140 string => {
141 callbacks => {
142 string => sub {
143 ( defined $_[0] && !ref $_[0] && length $_[0] )
144 or die { error => 'not a string' };
145 },
146 },
147 },
148 }
149 );
150 }
151
152 sub validate3 {
153 validate(
154 @_, {
155 string => {
156 callbacks => {
157 string => sub {
158 ( defined $_[0] && !ref $_[0] && length $_[0] )
159 or die;
160 },
161 },
162 },
163 }
164 );
165 }
166
167 sub validate4 {
168 validate(
169 @_, {
170 string => {
171 callbacks => {
172 string => sub {
173 return defined $_[0] && !ref $_[0] && length $_[0];
174 },
175 },
176 },
177 }
178 );
179 }
180
181 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 BEGIN {
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw( validate SCALAR );
16 use Test::More;
17
18 for my $i ( 1 .. 1000 ) {
19 ok( bar(), 'bar()' );
20 is( foo( foo => $i ), $i, "reentrant validation works ($i)" );
21 }
22
23 done_testing();
24
25 sub foo {
26 my %p = validate(
27 @_,
28 {
29 foo => {
30 callbacks => {
31 'call bar' => sub { bar() }
32 },
33 },
34 },
35 );
36
37 return $p{foo};
38 }
39
40 sub bar {
41 my %p = baz( baz => 42 );
42
43 return $p{baz} == 42;
44 }
45
46 sub baz {
47 my %p = validate(
48 @_,
49 {
50 baz => {
51 type => SCALAR,
52 callbacks => {
53 'is num' => sub { $_[0] =~ /^\d+$/ },
54 },
55 },
56 },
57 );
58
59 return %p;
60 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN {
14 $ENV{PV_TEST_PERL} = 1;
15 $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1;
16 }
17
18 use Module::Implementation 0.04 ();
19 use Params::Validate;
20
21 is(
22 Module::Implementation::implementation_for('Params::Validate'),
23 'PP',
24 'PP implementation is loaded when env var is set'
25 );
26
27 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN { $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1 }
14
15 use Module::Implementation 0.04 ();
16 use Params::Validate;
17
18 is(
19 Module::Implementation::implementation_for('Params::Validate'),
20 'XS',
21 'XS implementation is loaded by default'
22 );
23
24 done_testing();
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN {
14 $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'XS';
15 $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1;
16 }
17
18 use Params::Validate qw( validate SCALAR );
19
20 eval { foo( { a => 1 } ) };
21
22 ok(1, 'did not segfault');
23
24 done_testing();
25
26 sub foo {
27 validate(
28 @_,
29 {
30 a => { type => SCALAR, depends => ['%s%s%s'] },
31 }
32 );
33 }
0
1 BEGIN {
2 unless ($ENV{AUTHOR_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for testing by the author');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN {
14 $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'XS';
15 $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1;
16 }
17
18 use Params::Validate qw( validate_with );
19
20 my $alloc_size;
21 for my $i ( 0 .. 15 ) {
22 $alloc_size = 2**$i;
23 test_array_spec(undef);
24 }
25
26 ok( 1, 'array validation succeeded with stack realloc' );
27
28 for my $i ( 0 .. 15 ) {
29 $alloc_size = 2**$i;
30 test_hash_spec( a => undef );
31 }
32
33 ok( 1, 'hash validation succeeded with stack realloc' );
34
35 done_testing();
36
37 sub grow_stack {
38 my @stuff = (1) x $alloc_size;
39
40 # "validation" always succeeds - we just need the stack to grow inside a
41 # callback to trigger the bug.
42 return 1;
43 }
44
45 sub test_array_spec {
46 my @args = validate_with(
47 params => \@_,
48 spec => [ { callbacks => { grow_stack => \&grow_stack } } ],
49 );
50 }
51
52 sub test_hash_spec {
53 my %args = validate_with(
54 params => \@_,
55 spec => {
56 a => { callbacks => { grow_stack => \&grow_stack } },
57 },
58 );
59 }
+0
-99
t/release-memory-leak.t less more
0
1 BEGIN {
2 unless ($ENV{RELEASE_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for release candidate testing');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::LeakTrace qw( no_leaks_ok );
12 use Test::More;
13
14 use Params::Validate qw( validate );
15
16 subtest(
17 'callback with default error' => sub {
18 no_leaks_ok( sub { val1( foo => 42 ); }, 'validation passes' );
19 local $TODO = 'Not sure if all the leaks are in Carp or not';
20 no_leaks_ok(
21 sub {
22 eval { val1( foo => 'forty two' ) };
23 },
24 'validation fails'
25 );
26 },
27 );
28
29 subtest(
30 'callback that dies with string' => sub {
31 no_leaks_ok( sub { val2( foo => 42 ); }, 'validation passes' );
32 local $TODO = 'Not sure if all the leaks are in Carp or not';
33 no_leaks_ok(
34 sub {
35 eval { val2( foo => 'forty two' ) };
36 },
37 'validation fails'
38 );
39 },
40 );
41
42 subtest(
43 'callback that dies with object' => sub {
44 no_leaks_ok( sub { val3( foo => 42 ); }, 'validation passes' );
45 no_leaks_ok(
46 sub {
47 eval { val3( foo => 'forty two' ) };
48 },
49 'validation fails'
50 );
51 },
52 );
53
54 done_testing();
55
56 sub val1 {
57 validate(
58 @_,
59 {
60 foo => {
61 callbacks => {
62 'is int' => sub { $_[0] =~ /^[0-9]+$/ }
63 }
64 },
65 },
66 );
67 }
68
69 sub val2 {
70 validate(
71 @_,
72 {
73 foo => {
74 callbacks => {
75 'is int' => sub {
76 $_[0] =~ /^[0-9]+$/ or die "$_[0] is not an integer";
77 }
78 }
79 },
80 },
81 );
82 }
83
84 sub val3 {
85 validate(
86 @_,
87 {
88 foo => {
89 callbacks => {
90 'is int' => sub {
91 $_[0] =~ /^[0-9]+$/
92 or die { error => "$_[0] is not an integer" };
93 }
94 }
95 },
96 },
97 );
98 }
+0
-21
t/release-pp-01-validate.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Standard;
19 PVTests::Standard::run_tests();
20
+0
-24
t/release-pp-02-noop.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Standard;
21 PVTests::Standard::run_tests();
22
23
+0
-21
t/release-pp-04-defaults.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Defaults;
19 PVTests::Defaults::run_tests();
20
+0
-23
t/release-pp-05-noop_default.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Defaults;
21 PVTests::Defaults::run_tests();
22
+0
-52
t/release-pp-06-options.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests;
19 use Test::More;
20
21 use Params::Validate qw(:all);
22
23 validation_options( stack_skip => 2 );
24
25 sub foo {
26 my %p = validate( @_, { bar => 1 } );
27 }
28
29 sub bar { foo(@_) }
30
31 sub baz { bar(@_) }
32
33 eval { baz() };
34
35 like( $@, qr/mandatory.*missing.*call to main::bar/i );
36
37 validation_options( stack_skip => 3 );
38
39 eval { baz() };
40 like( $@, qr/mandatory.*missing.*call to main::baz/i );
41
42 validation_options( on_fail => sub { die bless { hash => 'ref' }, 'Dead' } );
43
44 eval { baz() };
45
46 my $e = $@;
47 is( $e->{hash}, 'ref' );
48 ok( eval { $e->isa('Dead'); 1; } );
49
50 done_testing();
51
+0
-21
t/release-pp-07-with.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::With;
19 PVTests::With::run_tests();
20
+0
-23
t/release-pp-08-noop_with.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::With;
21 PVTests::With::run_tests();
22
+0
-21
t/release-pp-09-regex.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Regex;
19 PVTests::Regex::run_tests();
20
+0
-23
t/release-pp-10-noop_regex.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Regex;
21 PVTests::Regex::run_tests();
22
+0
-21
t/release-pp-11-cb.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 use PVTests::Callbacks;
19 PVTests::Callbacks::run_tests();
20
+0
-23
t/release-pp-12-noop_cb.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 BEGIN { $ENV{PERL_NO_VALIDATION} = 1 }
19
20 use PVTests::Callbacks;
21 PVTests::Callbacks::run_tests();
22
+0
-23
t/release-pp-13-taint.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use File::Spec;
16 use lib File::Spec->catdir( 't', 'lib' );
17
18 eval { "$0$^X" && kill 0; 1 };
19
20 use PVTests::Standard;
21 PVTests::Standard::run_tests();
22
+0
-41
t/release-pp-14-no_validate.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use lib './t';
16
17 use Params::Validate qw(validate);
18
19 use Test::More;
20 plan tests => $] == 5.006 ? 2 : 3;
21
22 eval { foo() };
23 like( $@, qr/parameter 'foo'/ );
24
25 {
26 local $Params::Validate::NO_VALIDATION = 1;
27
28 eval { foo() };
29 is( $@, q{} );
30 }
31
32 unless ( $] == 5.006 ) {
33 eval { foo() };
34 like( $@, qr/parameter 'foo'/ );
35 }
36
37 sub foo {
38 validate( @_, { foo => 1 } );
39 }
40
+0
-111
t/release-pp-15-case.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More;
16
17 use Params::Validate qw(validate validate_with);
18
19 my @testset;
20
21 # Generate test cases ...
22 BEGIN {
23 my @lower_case_args = ( foo => 1 );
24 my @upper_case_args = ( FOO => 1 );
25 my @mixed_case_args = ( FoO => 1 );
26
27 my %lower_case_spec = ( foo => 1 );
28 my %upper_case_spec = ( FOO => 1 );
29 my %mixed_case_spec = ( FoO => 1 );
30
31 my %arglist = (
32 lower => \@lower_case_args,
33 upper => \@upper_case_args,
34 mixed => \@mixed_case_args
35 );
36
37 my %speclist = (
38 lower => \%lower_case_spec,
39 upper => \%upper_case_spec,
40 mixed => \%mixed_case_spec
41 );
42
43 # XXX - make subs such that user gets to see the error message
44 # when a test fails
45 my $ok_sub = sub {
46 if ($@) {
47 print STDERR $@;
48 }
49 !$@;
50 };
51
52 my $nok_sub = sub {
53 my $ok = ( $@ =~ /not listed in the validation options/ );
54 unless ($ok) {
55 print STDERR $@;
56 }
57 $ok;
58 };
59
60 # generate testcases on the fly (I'm too lazy)
61 for my $ignore_case (qw( 0 1 )) {
62 for my $args ( keys %arglist ) {
63 for my $spec ( keys %speclist ) {
64 push @testset, {
65 params => $arglist{$args},
66 spec => $speclist{$spec},
67 expect => (
68 $ignore_case ? $ok_sub
69 : $args eq $spec ? $ok_sub
70 : $nok_sub
71 ),
72 ignore_case => $ignore_case
73 };
74 }
75 }
76 }
77 }
78
79 plan tests => ( scalar @testset ) * 2;
80
81 {
82
83 # XXX - "called" will be all messed up, but what the heck
84 foreach my $case (@testset) {
85 my %args = eval {
86 validate_with(
87 params => $case->{params},
88 spec => $case->{spec},
89 ignore_case => $case->{ignore_case}
90 );
91 };
92
93 ok( $case->{expect}->(%args) );
94 }
95
96 # XXX - make sure that it works from validation_options() as well
97 foreach my $case (@testset) {
98 Params::Validate::validation_options(
99 ignore_case => $case->{ignore_case} );
100
101 my %args = eval {
102 my @args = @{ $case->{params} };
103 validate( @args, $case->{spec} );
104 };
105
106 ok( $case->{expect}->(%args) );
107 }
108 }
109
110
+0
-84
t/release-pp-16-normalize.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_with);
16 use Test::More;
17
18 my $ucfirst_normalizer = sub { return ucfirst lc $_[0] };
19
20 sub sub1 {
21 my %args = validate_with(
22 params => \@_,
23 spec => { PaRaMkEy => 1 },
24 normalize_keys => $ucfirst_normalizer
25 );
26
27 return $args{Paramkey};
28 }
29
30 sub sub2 {
31
32 # verify that normalize_callback surpresses ignore_case
33 my %args = validate_with(
34 params => \@_,
35 spec => { PaRaMkEy => 1 },
36 normalize_keys => $ucfirst_normalizer,
37 ignore_case => 1
38 );
39
40 return $args{Paramkey};
41 }
42
43 sub sub3 {
44
45 # verify that normalize_callback surpresses strip_leading
46 my %args = validate_with(
47 params => \@_,
48 spec => { -PaRaMkEy => 1 },
49 normalize_keys => $ucfirst_normalizer,
50 strip_leading => '-'
51 );
52
53 return $args{-paramkey};
54 }
55
56 sub sub4 {
57 my %args = validate_with(
58 params => \@_,
59 spec => { foo => 1 },
60 normalize_keys => sub {undef}
61 );
62 }
63
64 sub sub5 {
65 my %args = validate_with(
66 params => \@_,
67 spec => { foo => 1 },
68 normalize_keys => sub { return 'a' },
69 );
70 }
71
72 ok( eval { sub1( pArAmKeY => 1 ) } );
73 ok( eval { sub2( pArAmKeY => 1 ) } );
74 ok( eval { sub3( -pArAmKeY => 1 ) } );
75
76 eval { sub4( foo => 5 ) };
77 like( $@, qr/normalize_keys.+a defined value/ );
78
79 eval { sub5( foo => 5, bar => 5 ) };
80 like( $@, qr/normalize_keys.+already exists/ );
81
82 done_testing();
83
+0
-91
t/release-pp-17-callbacks.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_pos SCALAR);
16 use Test::More;
17
18 {
19 my @p = ( foo => 1, bar => 2 );
20
21 eval {
22 validate(
23 @p, {
24 foo => {
25 type => SCALAR,
26 callbacks => {
27 'bigger than bar' => sub { $_[0] > $_[1]->{bar} }
28 },
29 },
30 bar => { type => SCALAR },
31 }
32 );
33 };
34
35 like( $@, qr/bigger than bar/ );
36
37 $p[1] = 3;
38 eval {
39 validate(
40 @p, {
41 foo => {
42 type => SCALAR,
43 callbacks => {
44 'bigger than bar' => sub { $_[0] > $_[1]->{bar} }
45 },
46 },
47 bar => { type => SCALAR },
48 }
49 );
50 };
51
52 is( $@, q{} );
53 }
54
55 {
56 my @p = ( 1, 2, 3 );
57 eval {
58 validate_pos(
59 @p, {
60 type => SCALAR,
61 callbacks => {
62 'bigger than [1]' => sub { $_[0] > $_[1]->[1] }
63 }
64 },
65 { type => SCALAR },
66 { type => SCALAR },
67 );
68 };
69
70 like( $@, qr/bigger than \[1\]/ );
71
72 $p[0] = 5;
73 eval {
74 validate_pos(
75 @p, {
76 type => SCALAR,
77 callbacks => {
78 'bigger than [1]' => sub { $_[0] > $_[1]->[1] }
79 }
80 },
81 { type => SCALAR },
82 { type => SCALAR },
83 );
84 };
85
86 is( $@, q{} );
87 }
88
89 done_testing();
90
+0
-181
t/release-pp-18-depends.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_pos);
16 use Test::More;
17
18 {
19 my %spec = (
20 foo => { optional => 1, depends => 'bar' },
21 bar => { optional => 1 },
22 );
23
24 my @args = ( bar => 1 );
25
26 eval { validate( @args, \%spec ) };
27
28 is( $@, q{}, "validate() single depends(1): no depends, positive" );
29
30 @args = ( foo => 1, bar => 1 );
31 eval { validate( @args, \%spec ) };
32
33 is( $@, q{}, "validate() single depends(2): with depends, positive" );
34
35 @args = ( foo => 1 );
36 eval { validate( @args, \%spec ) };
37
38 ok( $@, "validate() single depends(3.a): with depends, negative" );
39 like(
40 $@,
41 qr(^Parameter 'foo' depends on parameter 'bar', which was not given),
42 "validate() single depends(3.b): check error string"
43 );
44 }
45
46 {
47 my %spec = (
48 foo => { optional => 1, depends => [qw(bar baz)] },
49 bar => { optional => 1 },
50 baz => { optional => 1 },
51 );
52
53 # positive, no depends (single, multiple)
54 my @args = ( bar => 1 );
55 eval { validate( @args, \%spec ) };
56 is(
57 $@, q{},
58 "validate() multiple depends(1): no depends, single arg, positive"
59 );
60
61 @args = ( bar => 1, baz => 1 );
62 eval { validate( @args, \%spec ) };
63
64 is(
65 $@, q{},
66 "validate() multiple depends(2): no depends, multiple arg, positive"
67 );
68
69 @args = ( foo => 1, bar => 1, baz => 1 );
70 eval { validate( @args, \%spec ) };
71
72 is( $@, q{}, "validate() multiple depends(3): with depends, positive" );
73
74 @args = ( foo => 1, bar => 1 );
75 eval { validate( @args, \%spec ) };
76
77 ok(
78 $@,
79 "validate() multiple depends(4.a): with depends, negative, multiple missing"
80 );
81 like(
82 $@,
83 qr(^Parameter 'foo' depends on parameter 'baz', which was not given),
84 "validate() multiple depends (4.b): check error string"
85 );
86
87 @args = ( foo => 1 );
88 eval { validate( @args, \%spec ) };
89
90 ok(
91 $@,
92 "validate() multiple depends(5.a): with depends, negative, multiple missing"
93 );
94 like(
95 $@,
96 qr(^Parameter 'foo' depends on parameter '(bar|baz)', which was not given),
97 "validate() multiple depends (5.b): check error string"
98 );
99 }
100
101 {
102
103 # bad depends
104 my %spec = (
105 foo => { optional => 1, depends => { 'bar' => 1 } },
106 bar => { optional => 1 },
107 );
108
109 my @args = ( foo => 1 );
110 eval { validate( @args, \%spec ) };
111
112 ok( $@, "validate() bad depends spec (1.a): depends is a hashref" );
113 like(
114 $@,
115 qr(^Arguments to 'depends' must be a scalar or arrayref),
116 "validate() bad depends spec (1.a): check error string"
117 );
118 }
119
120 {
121 my @spec = ( { optional => 1 } );
122
123 my @args = qw(1);
124 eval { validate_pos( @args, @spec ) };
125
126 is( $@, q{}, "validate_pos() no depends, positive" );
127 }
128
129 {
130 my @spec = ( { optional => 1, depends => 2 }, { optional => 1 } );
131
132 my @args = qw(1 1);
133 eval { validate_pos( @args, @spec ) };
134
135 is(
136 $@, q{},
137 "validate_pos() single depends (1): with depends, positive"
138 );
139 }
140
141 {
142 my @spec = (
143 { optional => 1, depends => 4 },
144 { optional => 1 }, { optional => 1 },
145 { optional => 1 }
146 );
147
148 my @args = qw(1 0);
149 eval { validate_pos( @args, @spec ) };
150
151 ok( $@, "validate_pos() single depends (2.a): with depends, negative" );
152 like(
153 $@,
154 qr(^Parameter #1 depends on parameter #4, which was not given),
155 "validate_pos() single depends (2.b): check error"
156 );
157 }
158
159 {
160 my @spec = (
161 { optional => 1, depends => [ 2, 3 ] },
162 { optional => 1 },
163 0
164 );
165 my @args = qw(1);
166 eval { validate_pos( @args, @spec ) };
167
168 ok(
169 $@,
170 "validate_pos() multiple depends (1.a): with depends, bad args negative"
171 );
172 like(
173 $@,
174 qr{^Arguments to 'depends' for validate_pos\(\) must be a scalar},
175 "validate_pos() multiple depends (1.b): check error"
176 );
177 }
178
179 done_testing();
180
+0
-99
t/release-pp-19-untaint.t less more
0 #!/usr/bin/perl -T
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12
13 use strict;
14 use warnings;
15
16 use Test::Requires {
17 'Test::Taint' => 0.02,
18 };
19
20 use Params::Validate qw(validate validate_pos);
21 use Test::More;
22
23 taint_checking_ok('These tests are meaningless unless we are in taint mode.');
24
25 {
26 my $value = 7;
27 taint($value);
28
29 tainted_ok( $value, 'make sure $value is tainted' );
30
31 my @p = ( value => $value );
32 my %p = validate(
33 @p, {
34 value => {
35 regex => qr/^\d+$/,
36 untaint => 1,
37 },
38 },
39 );
40
41 untainted_ok( $p{value}, 'value is untainted after validation' );
42 }
43
44 {
45 my $value = 'foo';
46
47 taint($value);
48
49 tainted_ok( $value, 'make sure $value is tainted' );
50
51 my @p = ($value);
52 my ($new_value) = validate_pos(
53 @p, {
54 regex => qr/foo/,
55 untaint => 1,
56 },
57 );
58
59 untainted_ok( $new_value, 'value is untainted after validation' );
60 }
61
62 {
63 my $value = 7;
64 taint($value);
65
66 tainted_ok( $value, 'make sure $value is tainted' );
67
68 my @p = ( value => $value );
69 my %p = validate(
70 @p, {
71 value => {
72 regex => qr/^\d+$/,
73 },
74 },
75 );
76
77 tainted_ok( $p{value}, 'value is still tainted after validation' );
78 }
79
80 {
81 my $value = 'foo';
82
83 taint($value);
84
85 tainted_ok( $value, 'make sure $value is tainted' );
86
87 my @p = ($value);
88 my ($new_value) = validate_pos(
89 @p, {
90 regex => qr/foo/,
91 },
92 );
93
94 tainted_ok( $new_value, 'value is still tainted after validation' );
95 }
96
97 done_testing();
98
+0
-108
t/release-pp-21-can.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @p = ( foo => 'ClassCan' );
20
21 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
22
23 is( $@, q{} );
24
25 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
26
27 like( $@, qr/does not have the method: 'thingy'/ );
28 }
29
30 {
31 my @p = ( foo => undef );
32 eval { validate( @p, { foo => { can => 'baz' } }, ); };
33
34 like( $@, qr/does not have the method: 'baz'/ );
35 }
36
37 {
38 my $object = bless {}, 'ClassCan';
39 my @p = ( foo => $object );
40
41 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
42
43 is( $@, q{} );
44
45 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
46
47 like( $@, qr/does not have the method: 'thingy'/ );
48 }
49
50 {
51 my @p = ( foo => 'SubClass' );
52
53 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
54
55 is( $@, q{}, 'SubClass->can(cancan)' );
56
57 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
58
59 like( $@, qr/does not have the method: 'thingy'/ );
60 }
61
62 {
63 my $object = bless {}, 'SubClass';
64 my @p = ( foo => $object );
65
66 eval { validate( @p, { foo => { can => 'cancan' } }, ); };
67
68 is( $@, q{}, 'SubClass object->can(cancan)' );
69
70 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
71
72 like( $@, qr/does not have the method: 'thingy'/ );
73 }
74
75 {
76 my @p = ( foo => {} );
77 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
78 like( $@, qr/does not have the method: 'thingy'/, 'unblessed ref ->can' );
79
80 @p = ( foo => 27 );
81 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
82 like( $@, qr/does not have the method: 'thingy'/, 'number can' );
83
84 @p = ( foo => 'A String' );
85 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
86 like( $@, qr/does not have the method: 'thingy'/, 'string can' );
87
88 @p = ( foo => undef );
89 eval { validate( @p, { foo => { can => 'thingy' } }, ); };
90 like( $@, qr/does not have the method: 'thingy'/, 'undef can' );
91 }
92
93 done_testing();
94
95 package ClassCan;
96
97 sub can {
98 return 1 if $_[1] eq 'cancan';
99 return 0;
100 }
101
102 sub thingy {1}
103
104 package SubClass;
105
106 use base 'ClassCan';
107
+0
-50
t/release-pp-22-overload-can-bug.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 package Overloaded;
20
21 use overload 'bool' => sub {0};
22
23 sub new { bless {} }
24
25 sub foo {1}
26 }
27
28 my $ovl = Overloaded->new;
29
30 {
31 eval {
32 my @p = ( object => $ovl );
33 validate( @p, { object => { isa => 'Overloaded' } } );
34 };
35
36 is( $@, q{}, 'overloaded object->isa' );
37 }
38
39 {
40 eval {
41 my @p = ( object => $ovl );
42 validate( @p, { object => { can => 'foo' } } );
43 };
44
45 is( $@, q{}, 'overloaded object->foo' );
46 }
47
48 done_testing();
49
+0
-52
t/release-pp-23-readonly.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::Requires {
16 Readonly => '1.03',
17 'Scalar::Util' => '1.20',
18 };
19
20 use Params::Validate qw(validate validate_pos SCALAR);
21 use Test::More;
22
23 plan skip_all => 'These tests fail with Readonly 1.50 for some reason'
24 if Readonly::->VERSION() =~ /^v?1.5/;
25
26 {
27 Readonly my $spec => { foo => 1 };
28 my @p = ( foo => 'hello' );
29
30 eval { validate( @p, $spec ) };
31 is( $@, q{}, 'validate() call succeeded with Readonly spec hashref' );
32 }
33
34 {
35 Readonly my $spec => { type => SCALAR };
36 my @p = 'hello';
37
38 eval { validate_pos( @p, $spec ) };
39 is( $@, q{}, 'validate_pos() call succeeded with Readonly spec hashref' );
40 }
41
42 {
43 Readonly my %spec => ( foo => { type => SCALAR } );
44 my @p = ( foo => 'hello' );
45
46 eval { validate( @p, \%spec ) };
47 is( $@, q{}, 'validate() call succeeded with Readonly spec hash' );
48 }
49
50 done_testing();
51
+0
-134
t/release-pp-24-tied.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate validate_pos SCALAR);
16 use Test::More;
17
18 {
19 package Tie::SimpleArray;
20 use Tie::Array;
21 use base 'Tie::StdArray';
22 }
23
24 {
25
26 package Tie::SimpleHash;
27 use Tie::Hash;
28 use base 'Tie::StdHash';
29 }
30
31 {
32 tie my @p, 'Tie::SimpleArray';
33
34 my %spec = ( foo => 1 );
35 push @p, ( foo => 'hello' );
36
37 eval { validate( @p, \%spec ) };
38 warn $@ if $@;
39 is(
40 $@, q{},
41 'validate() call succeeded with tied params array and regular hashref spec'
42 );
43 }
44
45 SKIP:
46 {
47 skip 'Params::Validate segfaults with tied hash for spec', 1;
48
49 my @p;
50 tie my %spec, 'Tie::SimpleHash';
51
52 $spec{foo} = 1;
53 push @p, ( foo => 'hello' );
54
55 eval { validate( @p, \%spec ) };
56 warn $@ if $@;
57 is(
58 $@, q{},
59 'validate() call succeeded with regular params array and tied hashref spec'
60 );
61 }
62
63 SKIP:
64 {
65 skip 'Params::Validate segfaults with tied hash for spec', 1;
66
67 tie my @p, 'Tie::SimpleArray';
68 tie my %spec, 'Tie::SimpleHash';
69
70 $spec{foo} = 1;
71 push @p, ( foo => 'hello' );
72
73 eval { validate( @p, \%spec ) };
74 warn $@ if $@;
75 is(
76 $@, q{},
77 'validate() call succeeded with tied params array and tied hashref spec'
78 );
79 }
80
81 {
82 tie my @p, 'Tie::SimpleArray';
83 my %spec;
84
85 $spec{type} = SCALAR;
86 push @p, 'hello';
87
88 eval { validate_pos( @p, \%spec ) };
89 warn $@ if $@;
90 is(
91 $@, q{},
92 'validate_pos() call succeeded with tied params array and regular hashref spec'
93 );
94 }
95
96 SKIP:
97 {
98 skip 'Params::Validate segfaults with tied hash for spec', 1;
99
100 my @p;
101 tie my %spec, 'Tie::SimpleHash';
102
103 $spec{type} = SCALAR;
104 push @p, 'hello';
105
106 eval { validate_pos( @p, \%spec ) };
107 warn $@ if $@;
108 is(
109 $@, q{},
110 'validate_pos() call succeeded with regular params array and tied hashref spec'
111 );
112 }
113
114 SKIP:
115 {
116 skip 'Params::Validate segfaults with tied hash for spec', 1;
117
118 tie my @p, 'Tie::SimpleArray';
119 tie my %spec, 'Tie::SimpleHash';
120
121 $spec{type} = SCALAR;
122 push @p, 'hello';
123
124 eval { validate_pos( @p, \%spec ) };
125 warn $@ if $@;
126 is(
127 $@, q{},
128 'validate_pos() call succeeded with tied params array and tied hashref spec'
129 );
130 }
131
132 done_testing();
133
+0
-30
t/release-pp-25-undef-regex.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @w;
20 local $SIG{__WARN__} = sub { push @w, @_ };
21
22 my @p = ( foo => undef );
23 eval { validate( @p, { foo => { regex => qr/^bar/ } } ) };
24 ok( $@, 'validation failed' );
25 ok( !@w, 'no warnings' );
26 }
27
28 done_testing();
29
+0
-102
t/release-pp-26-isa.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @p = ( foo => 'ClassISA' );
20
21 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
22
23 is( $@, q{}, 'no error checking if ClassISA->isa(FooBar)' );
24
25 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
26
27 like( $@, qr/was not a 'Thingy'/ );
28 }
29
30 {
31 my @p = ( foo => undef );
32 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
33
34 like( $@, qr/was not a 'FooBar'/ );
35 }
36
37 {
38 my @p = ( foo => 'SubClass' );
39
40 eval { validate( @p, { foo => { isa => 'ClassISA' } }, ); };
41
42 is( $@, q{}, 'SubClass->isa(ClassISA)' );
43
44 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
45
46 is( $@, q{}, 'SubClass->isa(FooBar)' );
47
48 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
49
50 like( $@, qr/was not a 'Thingy'/ );
51 }
52
53 {
54 my @p = ( foo => bless {}, 'SubClass' );
55
56 eval { validate( @p, { foo => { isa => 'ClassISA' } }, ); };
57
58 is( $@, q{}, 'SubClass->isa(ClassISA)' );
59
60 eval { validate( @p, { foo => { isa => 'FooBar' } }, ); };
61
62 is( $@, q{}, 'SubClass->isa(FooBar)' );
63
64 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
65
66 like( $@, qr/was not a 'Thingy'/ );
67 }
68
69 {
70 my @p = ( foo => {} );
71 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
72 like( $@, qr/was not a 'Thingy'/, 'unblessed ref ->isa' );
73
74 @p = ( foo => 27 );
75 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
76 like( $@, qr/was not a 'Thingy'/, 'number isa' );
77
78 @p = ( foo => 'A String' );
79 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
80 like( $@, qr/was not a 'Thingy'/, 'string isa' );
81
82 @p = ( foo => undef );
83 eval { validate( @p, { foo => { isa => 'Thingy' } }, ); };
84 like( $@, qr/was not a 'Thingy'/, 'undef isa' );
85 }
86
87 done_testing();
88
89 package ClassISA;
90
91 sub isa {
92 return 1 if $_[1] eq 'FooBar';
93 return $_[0]->SUPER::isa( $_[1] );
94 }
95
96 sub thingy {1}
97
98 package SubClass;
99
100 use base 'ClassISA';
101
+0
-43
t/release-pp-27-string-as-type.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw(validate);
16 use Test::More;
17
18 {
19 my @p = ( foo => 1 );
20
21 eval { validate( @p, { foo => { type => 'SCALAR' } }, ); };
22
23 like(
24 $@,
25 qr/\QThe 'foo' parameter ("1") has a type specification which is not a number. It is a string - SCALAR/
26 );
27 }
28
29 {
30 my @p = ( foo => 1 );
31
32 eval { validate( @p, { foo => { type => undef } }, ); };
33
34 like(
35 $@,
36 qr/\QThe 'foo' parameter ("1") has a type specification which is not a number. It is undef/
37 );
38
39 }
40
41 done_testing();
42
+0
-106
t/release-pp-28-readonly-return.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14 use Test::More;
15
16 use Devel::Peek qw( SvREFCNT );
17 use File::Temp qw( tempfile );
18 use Params::Validate qw( validate SCALAR HANDLE );
19
20 {
21 my $fh = tempfile();
22 my @p = (
23 foo => 1,
24 bar => $fh,
25 );
26
27 my $ref = val1(@p);
28
29 eval { $ref->{foo} = 2 };
30 ok( !$@, 'returned hashref values are not read only' );
31 is( $ref->{foo}, 2, 'double check that setting value worked' );
32 is( $fh, $ref->{bar}, 'filehandle is not copied during validation' );
33 }
34
35 {
36
37 package ScopeTest;
38
39 my $live = 0;
40
41 sub new { $live++; bless {}, shift }
42 sub DESTROY { $live-- }
43
44 sub Live {$live}
45 }
46
47 {
48 my @p = ( foo => ScopeTest->new() );
49
50 is(
51 ScopeTest->Live(), 1,
52 'one live object'
53 );
54
55 my $ref = val2(@p);
56
57 isa_ok( $ref->{foo}, 'ScopeTest' );
58
59 @p = ();
60
61 is(
62 ScopeTest->Live(), 1,
63 'still one live object'
64 );
65
66 ok(
67 defined $ref->{foo},
68 'foo key stays in scope after original version goes out of scope'
69 );
70 is(
71 SvREFCNT( $ref->{foo} ), 1,
72 'ref count for reference is 1'
73 );
74
75 undef $ref->{foo};
76
77 is(
78 ScopeTest->Live(), 0,
79 'no live objects'
80 );
81 }
82
83 sub val1 {
84 my $ref = validate(
85 @_, {
86 foo => { type => SCALAR },
87 bar => { type => HANDLE, optional => 1 },
88 },
89 );
90
91 return $ref;
92 }
93
94 sub val2 {
95 my $ref = validate(
96 @_, {
97 foo => 1,
98 },
99 );
100
101 return $ref;
102 }
103
104 done_testing();
105
+0
-65
t/release-pp-29-taint-mode.t less more
0 #!perl -T
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12
13 use strict;
14 use warnings;
15
16 use Test::Requires {
17 'Test::Taint' => 0.02,
18 };
19
20 use Test::Fatal;
21 use Test::More;
22
23 use Params::Validate qw( validate validate_pos ARRAYREF );
24
25 taint_checking_ok('These tests are meaningless unless we are in taint mode.');
26
27 sub test1 {
28 my $def = $0;
29 tainted_ok( $def, 'make sure $def is tainted' );
30
31 # The spec is irrelevant, all that matters is that there's a
32 # tainted scalar as the default
33 my %p = validate( @_, { foo => { default => $def } } );
34 }
35
36 {
37 is(
38 exception { test1() },
39 undef,
40 'no taint error when we validate with tainted default value'
41 );
42 }
43
44 sub test2 {
45 return validate_pos( @_, { regex => qr/^b/ } );
46 }
47
48 SKIP:
49 {
50 skip 'This test only passes on Perl 5.14+', 1
51 unless $] >= 5.014;
52
53 my @p = 'cat';
54 taint(@p);
55
56 like(
57 exception { test2(@p) },
58 qr/\QParameter #1 ("cat") to main::test2 did not pass regex check/,
59 'no taint error when we validate with tainted value values being validated'
60 );
61 }
62
63 done_testing();
64
+0
-64
t/release-pp-30-hashref-alteration.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14 use Test::More;
15
16 use Params::Validate qw( validate SCALAR );
17
18 {
19 my $p = { foo => 1 };
20
21 val($p);
22
23 is_deeply(
24 $p, { foo => 1 },
25 'validate does not alter hashref passed to val'
26 );
27
28 val2($p);
29
30 is_deeply(
31 $p, { foo => 1 },
32 'validate does not alter hashref passed to val, even with defaults being supplied'
33 );
34 }
35
36 sub val {
37 validate(
38 @_, {
39 foo => { optional => 1 },
40 bar => { optional => 1 },
41 baz => { optional => 1 },
42 buz => { optional => 1 },
43 },
44 );
45
46 return;
47 }
48
49 sub val2 {
50 validate(
51 @_, {
52 foo => { optional => 1 },
53 bar => { default => 42 },
54 baz => { optional => 1 },
55 buz => { optional => 1 },
56 },
57 );
58
59 return;
60 }
61
62 done_testing();
63
+0
-73
t/release-pp-31-incorrect-spelling.t less more
0 #!/usr/bin/perl -w
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12
13 use strict;
14 use warnings;
15
16 use Test::More;
17
18 use Params::Validate qw( validate validate_pos SCALAR );
19
20 plan skip_all => 'Spec validation is disabled for now';
21
22 {
23 my @p = ( foo => 1, bar => 2 );
24
25 eval {
26 validate(
27 @p, {
28 foo => {
29 type => SCALAR,
30 callbucks => {
31 'one' => sub {1}
32 },
33 },
34 bar => { type => SCALAR },
35 }
36 );
37 };
38
39 like( $@, qr/is not an allowed validation spec key/ );
40
41 eval {
42 validate(
43 @p, {
44 foo => {
45 hype => SCALAR,
46 callbacks => {
47 'one' => sub {1}
48 },
49 },
50 bar => { type => SCALAR },
51 }
52 );
53 };
54
55 like( $@, qr/is not an allowed validation spec key/ );
56 eval {
57 validate(
58 @p, {
59 foo => {
60 type => SCALAR,
61 regexp => qr/^\d+$/,
62 },
63 bar => { type => SCALAR },
64 }
65 );
66 };
67
68 like( $@, qr/is not an allowed validation spec key/ );
69 }
70
71 done_testing();
72
+0
-50
t/release-pp-32-regex-as-value.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw( validate SCALAR SCALARREF );
16
17 use Test::More;
18 use Test::Fatal;
19
20 is(
21 exception { v( foo => qr/foo/ ) },
22 undef,
23 'no exception with regex object'
24 );
25
26 is(
27 exception { v( foo => 'foo' ) },
28 undef,
29 'no exception with plain scalar'
30 );
31
32 my $foo = 'foo';
33 is(
34 exception { v( foo => \$foo ) },
35 undef,
36 'no exception with scalar ref'
37 );
38
39 done_testing();
40
41 sub v {
42 validate(
43 @_, {
44 foo => { type => SCALAR | SCALARREF },
45 },
46 );
47 return;
48 }
49
+0
-36
t/release-pp-33-keep-errsv.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw( validate SCALAR );
16
17 use Test::More;
18
19 {
20 $@ = 'foo';
21 v( bar => 42 );
22
23 is(
24 $@,
25 'foo',
26 'calling validate() does not clobber'
27 );
28 }
29
30 done_testing();
31
32 sub v {
33 validate( @_, { bar => { type => SCALAR } } );
34 }
35
+0
-67
t/release-pp-34-recursive-validation.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::Fatal;
16 use Test::More;
17
18 {
19 package Foo;
20
21 use Params::Validate qw( validate SCALAR );
22
23 Params::Validate::validation_options( allow_extra => 1 );
24
25 sub test_foo {
26 my %p = validate( @_, { arg1 => { type => SCALAR } } );
27 print "test foo\n";
28 }
29 }
30
31 {
32 package Bar;
33
34 use Params::Validate qw( validate SCALAR );
35 Params::Validate::validation_options( allow_extra => 0 );
36
37 sub test_bar {
38
39 # catch die signal
40 local $SIG{__DIE__} = sub {
41
42 # we died from within Params::Validate (because of wrong_Arg) we
43 # call Foo::test_foo with OK args, but it'll die, because
44 # Params::Validate::PP::options is still set to the options of the
45 # Bar package, and so it won't retreive the one from Foo.
46 Foo::test_foo( arg1 => 1, extra_arg => 2 );
47 };
48
49 # this will die because the arg received is 'wrong_arg'
50 my %p = validate( @_, { arg1 => { type => SCALAR } } );
51 }
52 }
53
54 {
55 # This bug only manifests with the pure Perl code because of its use of local
56 # to remember the per-package options.
57 local $TODO = 'Not sure how to fix this one';
58 unlike(
59 exception { Bar::test_bar( bad_arg => 2 ) },
60 qr/was passed in the call to Foo::test_foo/,
61 'no exception from Foo::test_foo when when calling validate() from within a __DIE__ handler'
62 );
63 }
64
65 done_testing();
66
+0
-34
t/release-pp-35-default-xs-bug.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More 0.88;
16
17 use Params::Validate qw( :all );
18
19 default_test();
20
21 done_testing();
22
23 sub default_test {
24 my ( $first, $second ) = validate_pos(
25 @_,
26 { type => SCALAR, optional => 1 },
27 { type => SCALAR, optional => 1, default => 'must be second one' },
28 );
29
30 is( $first, undef, '01 no default for first' );
31 is( $second, 'must be second one', '01 default for second' );
32 }
33
+0
-55
t/release-pp-36-large-arrays.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::Fatal;
16 use Test::More;
17
18 {
19 package Foo;
20
21 use Params::Validate qw( validate ARRAYREF );
22
23 sub v1 {
24 my %p = validate(
25 @_, {
26 array => {
27 callbacks => {
28 'checking array contents' => sub {
29 for my $x ( @{ $_[0] } ) {
30 return 0 unless defined $x && !ref $x;
31 }
32 return 1;
33 },
34 }
35 }
36 }
37 );
38 return $p{array};
39 }
40 }
41
42 {
43 for my $size ( 100, 1_000, 100_000 ) {
44 my @array = ('x') x $size;
45 is_deeply(
46 Foo::v1( array => \@array ),
47 \@array,
48 "validate() handles $size element array correctly"
49 );
50 }
51 }
52
53 done_testing();
54
+0
-65
t/release-pp-37-exports.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More;
16 use Params::Validate ();
17
18 my @types = qw(
19 SCALAR
20 ARRAYREF
21 HASHREF
22 CODEREF
23 GLOB
24 GLOBREF
25 SCALARREF
26 HANDLE
27 BOOLEAN
28 UNDEF
29 OBJECT
30 );
31
32 my @subs = qw(
33 validate
34 validate_pos
35 validation_options
36 validate_with
37 );
38
39 is_deeply(
40 [ sort @Params::Validate::EXPORT_OK ],
41 [ sort @types, @subs, 'set_options' ],
42 '@EXPORT_OK'
43 );
44
45 is_deeply(
46 [ sort keys %Params::Validate::EXPORT_TAGS ],
47 [qw( all types )],
48 'keys %EXPORT_TAGS'
49 );
50
51 is_deeply(
52 [ sort @{ $Params::Validate::EXPORT_TAGS{all} } ],
53 [ sort @types, @subs ],
54 '$EXPORT_TAGS{all}',
55 );
56
57 is_deeply(
58 [ sort @{ $Params::Validate::EXPORT_TAGS{types} } ],
59 [ sort @types ],
60 '$EXPORT_TAGS{types}',
61 );
62
63 done_testing();
64
+0
-183
t/release-pp-38-callback-message.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Test::More;
16 use Params::Validate qw( validate );
17
18 {
19 my $e = _test_args(
20 pos_int => 42,
21 string => 'foo',
22 );
23 is(
24 $e,
25 q{},
26 'no error with good args'
27 );
28 }
29
30 {
31 my $e = _test_args(
32 pos_int => 42,
33 string => [],
34 );
35 like(
36 $e,
37 qr/The 'string' parameter \("ARRAY\(.+\)"\) to main::validate1 did not pass the 'string' callback: ARRAY\(.+\) is not a string/,
38 'got error for bad string'
39 );
40 }
41
42 {
43 my $e = _test_args(
44 pos_int => 0,
45 string => 'foo',
46 );
47 like(
48 $e,
49 qr/\QThe 'pos_int' parameter ("0") to main::validate1 did not pass the 'pos_int' callback: 0 is not a positive integer/,
50 'got error for bad pos int (0)'
51 );
52 }
53
54 {
55 my $e = _test_args(
56 pos_int => 'bar',
57 string => 'foo',
58 );
59 like(
60 $e,
61 qr/\QThe 'pos_int' parameter ("bar") to main::validate1 did not pass the 'pos_int' callback: bar is not a positive integer/,
62 'got error for bad pos int (bar)'
63 );
64 }
65
66 {
67 my $e = do {
68 local $@;
69 eval { validate2( string => [] ); };
70 $@;
71 };
72
73 is_deeply(
74 $e,
75 { error => 'not a string' },
76 'ref thrown by callback is preserved, not stringified'
77 );
78 }
79
80 {
81 my $e = do {
82 local $@;
83 eval { validate3( string => [] ); };
84 $@;
85 };
86
87 like(
88 $e,
89 qr/\QThe 'string' parameter (\E.+?\Q) to main::validate3 did not pass the 'string' callback: Died at \E.+/,
90 'callback that dies with an empty string generates a sane error message'
91 );
92 }
93
94 {
95 my $e = do {
96 local $@;
97 eval { validate4( string => [] ); };
98 $@;
99 };
100
101 like(
102 $e,
103 qr/\QThe 'string' parameter (\E.+?\Q) to main::validate4 did not pass the 'string' callback\E\s+at/,
104 'callback that does not dies generates a sane error message'
105 );
106 }
107
108 sub _test_args {
109 local $@;
110 eval { validate1(@_) };
111 return $@;
112 }
113
114 sub validate1 {
115 validate(
116 @_, {
117 pos_int => {
118 callbacks => {
119 pos_int => sub {
120 $_[0] =~ /^[1-9][0-9]*$/
121 or die "$_[0] is not a positive integer\n";
122 },
123 },
124 },
125 string => {
126 callbacks => {
127 string => sub {
128 ( defined $_[0] && !ref $_[0] && length $_[0] )
129 or die "$_[0] is not a string\n";
130 },
131 },
132 },
133 }
134 );
135 }
136
137 sub validate2 {
138 validate(
139 @_, {
140 string => {
141 callbacks => {
142 string => sub {
143 ( defined $_[0] && !ref $_[0] && length $_[0] )
144 or die { error => 'not a string' };
145 },
146 },
147 },
148 }
149 );
150 }
151
152 sub validate3 {
153 validate(
154 @_, {
155 string => {
156 callbacks => {
157 string => sub {
158 ( defined $_[0] && !ref $_[0] && length $_[0] )
159 or die;
160 },
161 },
162 },
163 }
164 );
165 }
166
167 sub validate4 {
168 validate(
169 @_, {
170 string => {
171 callbacks => {
172 string => sub {
173 return defined $_[0] && !ref $_[0] && length $_[0];
174 },
175 },
176 },
177 }
178 );
179 }
180
181 done_testing();
182
+0
-62
t/release-pp-39-reentrant.t less more
0
1
2 use Test::More;
3
4 BEGIN {
5 unless ( $ENV{RELEASE_TESTING} ) {
6 plan skip_all => 'these tests are for release testing';
7 }
8
9 $ENV{PV_TEST_PERL} = 1;
10 }
11
12 use strict;
13 use warnings;
14
15 use Params::Validate qw( validate SCALAR );
16 use Test::More;
17
18 for my $i ( 1 .. 1000 ) {
19 ok( bar(), 'bar()' );
20 is( foo( foo => $i ), $i, "reentrant validation works ($i)" );
21 }
22
23 done_testing();
24
25 sub foo {
26 my %p = validate(
27 @_,
28 {
29 foo => {
30 callbacks => {
31 'call bar' => sub { bar() }
32 },
33 },
34 },
35 );
36
37 return $p{foo};
38 }
39
40 sub bar {
41 my %p = baz( baz => 42 );
42
43 return $p{baz} == 42;
44 }
45
46 sub baz {
47 my %p = validate(
48 @_,
49 {
50 baz => {
51 type => SCALAR,
52 callbacks => {
53 'is num' => sub { $_[0] =~ /^\d+$/ },
54 },
55 },
56 },
57 );
58
59 return %p;
60 }
61
+0
-28
t/release-pp-is-loaded.t less more
0
1 BEGIN {
2 unless ($ENV{RELEASE_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for release candidate testing');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN {
14 $ENV{PV_TEST_PERL} = 1;
15 $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1;
16 }
17
18 use Module::Implementation 0.04 ();
19 use Params::Validate;
20
21 is(
22 Module::Implementation::implementation_for('Params::Validate'),
23 'PP',
24 'PP implementation is loaded when env var is set'
25 );
26
27 done_testing();
+0
-25
t/release-xs-is-loaded.t less more
0
1 BEGIN {
2 unless ($ENV{RELEASE_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for release candidate testing');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN { $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1 }
14
15 use Module::Implementation 0.04 ();
16 use Params::Validate;
17
18 is(
19 Module::Implementation::implementation_for('Params::Validate'),
20 'XS',
21 'XS implementation is loaded by default'
22 );
23
24 done_testing();
+0
-34
t/release-xs-segfault.t less more
0
1 BEGIN {
2 unless ($ENV{RELEASE_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for release candidate testing');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN {
14 $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'XS';
15 $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1;
16 }
17
18 use Params::Validate qw( validate SCALAR );
19
20 eval { foo( { a => 1 } ) };
21
22 ok(1, 'did not segfault');
23
24 done_testing();
25
26 sub foo {
27 validate(
28 @_,
29 {
30 a => { type => SCALAR, depends => ['%s%s%s'] },
31 }
32 );
33 }
+0
-60
t/release-xs-stack-realloc.t less more
0
1 BEGIN {
2 unless ($ENV{RELEASE_TESTING}) {
3 require Test::More;
4 Test::More::plan(skip_all => 'these tests are for release candidate testing');
5 }
6 }
7
8 use strict;
9 use warnings;
10
11 use Test::More;
12
13 BEGIN {
14 $ENV{PARAMS_VALIDATE_IMPLEMENTATION} = 'XS';
15 $ENV{PV_WARN_FAILED_IMPLEMENTATION} = 1;
16 }
17
18 use Params::Validate qw( validate_with );
19
20 my $alloc_size;
21 for my $i ( 0 .. 15 ) {
22 $alloc_size = 2**$i;
23 test_array_spec(undef);
24 }
25
26 ok( 1, 'array validation succeeded with stack realloc' );
27
28 for my $i ( 0 .. 15 ) {
29 $alloc_size = 2**$i;
30 test_hash_spec( a => undef );
31 }
32
33 ok( 1, 'hash validation succeeded with stack realloc' );
34
35 done_testing();
36
37 sub grow_stack {
38 my @stuff = (1) x $alloc_size;
39
40 # "validation" always succeeds - we just need the stack to grow inside a
41 # callback to trigger the bug.
42 return 1;
43 }
44
45 sub test_array_spec {
46 my @args = validate_with(
47 params => \@_,
48 spec => [ { callbacks => { grow_stack => \&grow_stack } } ],
49 );
50 }
51
52 sub test_hash_spec {
53 my %args = validate_with(
54 params => \@_,
55 spec => {
56 a => { callbacks => { grow_stack => \&grow_stack } },
57 },
58 );
59 }