—package
ICANN::RST::Spec;
# ABSTRACT: an object representing the RST test specifications.
use
Carp;
use
ICANN::RST::Case;
use
ICANN::RST::Error;
use
ICANN::RST::Input;
use
ICANN::RST::Plan;
use
ICANN::RST::Resource;
use
ICANN::RST::Suite;
use
ICANN::RST::Text;
use
URI;
use
YAML::XS;
use
strict;
$YAML::XS::Boolean
=
q{JSON::PP}
;
sub
url_from_release {
my
(
$package
,
$release
) =
@_
;
foreach
my
$asset
(@{
$release
->{assets}}) {
if
(
'rst-test-specs.yaml'
eq
$asset
->{name}) {
return
URI->new(
$asset
->{browser_download_url});
}
}
return
undef
;
}
sub
current_version {
shift
->url_from_release(mirror_json(
q{https://api.github.com/repos/icann/rst-test-specs/releases/latest}
)) }
sub
versions {
my
$package
=
shift
;
return
map
{
$package
->url_from_release(
$_
) } @{mirror_json(
q{https://api.github.com/repos/icann/rst-test-specs/releases}
)};
}
sub
new {
my
(
$package
,
$file
) =
@_
;
$file
||= mirror_file(
$package
->current_version);
my
$self
=
bless
(
{
'spec'
=> YAML::XS::LoadFile(
$file
),
'file'
=>
$file
},
$package
,
);
my
$v
= version->parse(
$self
->spec->{
'RST-Test-Plan-Schema-Version'
});
croak(
sprintf
(
"Unsupported schema version '%s', must be '%s'"
,
$v
, SCHEMA_VERSION))
unless
(SCHEMA_VERSION ==
$v
);
#
# precompile everything
#
$self
->{
'_preamble'
} = ICANN::RST::Text->new(
$self
->spec->{
'Preamble'
});
$self
->{
'_plans'
} = [
sort
{
$a
->order <=>
$b
->order } pairmap { ICANN::RST::Plan -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Test-Plans'
}} ];
$self
->{
'_suites'
} = [
sort
{
$a
->order <=>
$b
->order } pairmap { ICANN::RST::Suite -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Test-Suites'
}} ];
$self
->{
'_cases'
} = [
sort
{
$a
->id cmp
$b
->id } pairmap { ICANN::RST::Case -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Test-Cases'
}} ];
$self
->{
'_inputs'
} = [
sort
{
$a
->id cmp
$b
->id } pairmap { ICANN::RST::Input -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Input-Parameters'
}} ];
$self
->{
'_resources'
} = [
sort
{
$a
->id cmp
$b
->id } pairmap { ICANN::RST::Resource -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Resources'
}} ];
$self
->{
'_errors'
} = [
sort
{
$a
->id cmp
$b
->id } pairmap { ICANN::RST::Error -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Errors'
}} ];
$self
->{
'_providers'
} = [
sort
{
$a
->id cmp
$b
->id } pairmap { ICANN::RST::DataProvider -> new(
$a
,
$b
,
$self
) } %{
$self
->spec->{
'Data-Providers'
}} ];
return
$self
;
}
sub
changelog {
my
$self
=
shift
;
my
@log
;
foreach
my
$date
(
reverse
(
sort
(
keys
(%{
$self
->spec->{
'ChangeLog'
}})))) {
push
(
@log
, ICANN::RST::ChangeLog->new(
$date
,
$self
->spec->{
'ChangeLog'
}->{
$date
},
$self
));
}
return
@log
;
}
sub
spec {
$_
[0]->{
'spec'
} }
sub
schemaVersion {
$_
[0]->spec->{
'RST-Test-Plan-Schema-Version'
} }
sub
version {
$_
[0]->spec->{
'Version'
} }
sub
lastUpdated {
$_
[0]->spec->{
'Last-Updated'
} }
sub
contactName {
$_
[0]->spec->{
'Contact'
}->{
'Name'
} }
sub
contactOrg {
$_
[0]->spec->{
'Contact'
}->{
'Organization'
} }
sub
contactEmail {
$_
[0]->spec->{
'Contact'
}->{
'Email'
} }
sub
preamble {
$_
[0]->{
'_preamble'
} }
sub
plans { @{
$_
[0]->{
'_plans'
} } }
sub
suites { @{
$_
[0]->{
'_suites'
} } }
sub
cases { @{
$_
[0]->{
'_cases'
} } }
sub
inputs { @{
$_
[0]->{
'_inputs'
} } }
sub
resources { @{
$_
[0]->{
'_resources'
} } }
sub
errors { @{
$_
[0]->{
'_errors'
} } }
sub
providers { @{
$_
[0]->{
'_providers'
} } }
sub
plan {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->plans) }
sub
suite {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->suites) }
sub
case {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->cases) }
sub
resource {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->resources) }
sub
error {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->errors) }
sub
input {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->inputs) }
sub
provider {
my
(
$self
,
$id
) =
@_
;
return
$self
->find(
$id
,
$self
->providers) }
sub
find {
my
(
$self
,
$needle
,
@haystack
) =
@_
;
foreach
my
$stick
(
@haystack
) {
return
$stick
if
(
$stick
->id eq
$needle
);
}
carp(
"object '$needle' not found"
);
return
undef
;
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
ICANN::RST::Spec - an object representing the RST test specifications.
=head1 VERSION
version 0.02
=head1 METHODS
=head2 new($file)
Constructor. C<$file> is the YAML file. If not provided, the most recent
version will be retried from
=head2 current_version()
Returns a L<URI> object that points to the URL of the most recently released
version of the test specs.
=head2 versions()
Returns an array of L<URI> objects pointing to all available released versions
of the test specs.
=head2 schemaVersion()
Returns a string containing the schema version of the spec file.
=head2 version()
Returns a string containing the version of the spec file.
=head2 lastUpdated()
Returns a string containing the date the spec was last updated.
=head2 preamble()
Returns a L<ICANN::RST::Text> object containing the preamble.
=head2 changelog()
Returns an array of L<ICANN::RST::ChangeLog> objects.
=head2 contactName()
Returns a string containing the contact name.
=head2 contactOrg()
Returns a string containing the contact organisation.
=head2 contactEmail()
Returns a string containing the contact email.
=head2 plans()
Returns an array of L<ICANN::RST::Plan> objects.
=head2 plan($id)
Returns the L<ICANN::RST::Plan> object with the given ID.
=head2 suites()
Returns an array of L<ICANN::RST::Suite> objects.
=head2 suite($id)
Returns the L<ICANN::RST::Suite> object with the given ID.
=head2 resources()
Returns an array of L<ICANN::RST::Resource> objects.
=head2 resource($id)
Returns the L<ICANN::RST::Resource> object with the given ID.
=head2 cases()
Returns an array of L<ICANN::RST::Case> objects.
=head2 case($id)
Returns the L<ICANN::RST::Case> object with the given ID.
=head2 inputs()
Returns an array of L<ICANN::RST::Input> objects.
=head2 input($id)
Returns the L<ICANN::RST::Input> object with the given ID.
=head2 errors()
Returns an array of L<ICANN::RST::Error> objects.
=head2 error($id)
=head2 providers()
Returns an array of L<ICANN::RST::Error> objects.
=head2 provider($id)
Returns the L<ICANN::RST::DataProvider> object with the given ID.
=head2 spec()
Returns a hashref of the specification data structure.
=head1 AUTHOR
Gavin Brown <gavin.brown@icann.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2025 by Internet Corporation for Assigned Names and Number (ICANN).
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut