[Rt-commit] r5423 - in Test-Chimps: . trunk trunk/bin
trunk/examples trunk/lib/Test/Smoke/Report
zev at bestpractical.com
zev at bestpractical.com
Fri Jun 23 17:32:35 EDT 2006
Author: zev
Date: Fri Jun 23 17:32:32 2006
New Revision: 5423
Added:
Test-Chimps/trunk/examples/
Test-Chimps/trunk/examples/list.tmpl
Modified:
Test-Chimps/ (props changed)
Test-Chimps/trunk/Makefile.PL
Test-Chimps/trunk/bin/receive_report.pl
Test-Chimps/trunk/lib/Test/Smoke/Report.pm
Test-Chimps/trunk/lib/Test/Smoke/Report/Client.pm
Test-Chimps/trunk/lib/Test/Smoke/Report/Server.pm
Log:
r4187 at galvatron (orig r4): zev | 2006-06-20 17:58:25 -0400
r4127 at galvatron: zev | 2006-06-18 22:17:12 -0400
listing works
Modified: Test-Chimps/trunk/Makefile.PL
==============================================================================
--- Test-Chimps/trunk/Makefile.PL (original)
+++ Test-Chimps/trunk/Makefile.PL Fri Jun 23 17:32:32 2006
@@ -6,7 +6,7 @@
# Specific dependencies
requires('Algorithm::TokenBucket');
-requires('HTML::Template');
+requires('HTML::Mason');
requires('LWP::UserAgent');
requires('Module::CoreList');
requires('Params::Validate');
Modified: Test-Chimps/trunk/bin/receive_report.pl
==============================================================================
--- Test-Chimps/trunk/bin/receive_report.pl (original)
+++ Test-Chimps/trunk/bin/receive_report.pl Fri Jun 23 17:32:32 2006
@@ -4,6 +4,50 @@
use Test::Smoke::Report::Server;
-my $server = Test::Smoke::Report::Server->new(base_dir => '/var/www/bps-smokes');
+my $server = Test::Smoke::Report::Server->new(base_dir => '/var/www/bps-smokes',
+ validate_extra =>
+ { base_dir =>
+ { type => SCALAR,
+ optional => 0 },
+ bucket_file =>
+ { type => SCALAR,
+ default => 'bucket.dat',
+ optional => 1 },
+ burst_rate =>
+ { type => SCALAR,
+ optional => 1,
+ default => 5,
+ callbacks =>
+ { "greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ max_rate =>
+ { type => SCALAR,
+ default => (1 / 30),
+ optional => 1,
+ callbacks =>
+ {"greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ max_size =>
+ { type => SCALAR,
+ default => 2**20 * 3.0,
+ optional => 1,
+ callbacks =>
+ { "greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ max_smokes_same_category =>
+ { type => SCALAR,
+ default => 5,
+ optional => 1,
+ callbacks =>
+ { "greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ report_dir =>
+ { type => SCALAR,
+ default => 'reports',
+ optional => 1 },
+ validate_extra =>
+ { type => HASHREF,
+ optional => 1 }});
+
$server->handle_request;
Added: Test-Chimps/trunk/examples/list.tmpl
==============================================================================
--- (empty file)
+++ Test-Chimps/trunk/examples/list.tmpl Fri Jun 23 17:32:32 2006
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+ <title>Smoke Reports</title>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+
+ <style type="text/css">
+ body {
+ background-color: white;
+ margin: 0;
+
+ font-family: sans-serif;
+ line-height: 1.3em;
+ font-size: 95%;
+ }
+
+ h1, h2 {
+ background-color: #313052;
+ color: white;
+ padding: 10px;
+ }
+
+ th { text-align: left; }
+ .category { padding-top: 30px; border-bottom: 2px solid #313052; }
+ .subcategory { padding-top: 10px; border-bottom: 1px solid #313052; }
+ .report_summary { padding-left: 40px; }
+ .report_details { padding-left: 80px; padding-bottom: 10px; }
+
+ p, dl, pre, table { margin: 15px; }
+ dt { font-weight: bold; }
+ dd+dt { margin-top: 1em; }
+ .leftsep { padding-left: 10px; }
+ .num { text-align: right; }
+
+ .details { display: none; }
+ .expander { color: blue; cursor: pointer; } /* hack? */
+
+ .tests_ok { color: #050; }
+ .tests_failed { color: #500; }
+ .tests_todo { color: #030; }
+ .tests_skipped { color: #555; }
+ .tests_unexpect { color: #550; }
+ </style>
+
+ <script type="text/javascript">//<![CDATA[[
+ function toggle_visibility (id) {
+ var elem = document.getElementById("details_" + id),
+ expander = document.getElementById("expander_" + id);
+ if(elem.className == "details") {
+ elem.className = ""; /* hack? */
+ expander.innerHTML = "«";
+ } else {
+ elem.className = "details";
+ expander.innerHTML = "»";
+ }
+ }
+ //]]></script>
+</head>
+
+<body>
+ <h1>Smoke Reports</h1>
+
+ <p>
+ Note that old smoke reports may be automatically deleted, so you may not want
+ to link directly to a smoke.
+ </p>
+
+ <p>
+ Timezone is UTC
+ </p>
+
+ <table>
+% foreach my $category (keys %categories) {
+ <tr><th colspan="11" class="category"><% $category %></th></tr>
+% foreach my $subcategory (keys %{$categories{$category}}) {
+ <tr><th colspan="11" class="subcategory"><% $subcategory %></th></tr>
+% foreach my $report (@{$categories{$category}->{$subcategory}}) {
+% my $id = 5;
+% my $data = $report->extra_data;
+% my $model = Test::TAP::Model::Visual->new_with_struct($report->model_structure);
+ <tr>
+ <td class="report_summary"><% $data->{project} %></td>
+ <td>
+ r<% $data->{revision} %>
+ </td>
+ <td class="leftsep"><% $data->{timestamp} %></td>
+ <td class="leftsep num"><% $data->{duration} %></td>
+ <td class="leftsep num"><% $model->total_ratio %>> % ok</td>
+ <td class="leftsep num tests_total"><span title="<% $model->total_seen %> total"><% $model->total_seen %></span>:</td>
+ <td class="num tests_ok"><span title="<% $model->total_ok %> ok"><% $model->total_ok %></span>,</td>
+ <td class="num tests_failed"><span title="<% $model->total_failed %> failed"><% $model->total_failed %></span>,</td>
+ <td class="num tests_todo"><span title="<% $model->total_todo %> todo"><% $model->total_todo %></span>,</td>
+ <td class="num tests_skipped"><span title="<% $model->total_skipped %> skipped"><% $model->total_skipped %></span>,</td>
+ <td class="num tests_unexpect"><span title="<% $model->total_unexpectedly_succeeded %> unexpectedly succeeded"><% $model->total_unexpectedly_succeeded %></span></td>
+ <td><span title="Details" class="expander" onclick="toggle_visibility('<% $id %>')" id="expander_<% $id %>">»</span></td>
+ <td><a style="text-decoration: none" href="<tmpl_var name=link>" title="Full smoke report">»</a></td>
+ </tr>
+ <tr class="details" id="details_<% $id %>">
+ <td colspan="11" class="report_details">
+ <span class="tests_total"><% $model->total_seen %> test cases</span>:<br />
+ <span class="tests_ok"><% $model->total_ok %> ok</span>,
+ <span class="tests_failed"><% $model->total_failed %> failed</span>,
+ <span class="tests_todo"><% $model->total_todo %> todo</span>,<br />
+ <span class="tests_skipped"><% $model->total_skipped %> skipped</span> and
+ <span class="tests_unexpect"><% $model->total_unexpectedly_succeeded %> unexpectedly succeeded</span>
+ <br />
+ <a href="<tmpl_var name=link>" title="Full smoke report">View full smoke report</a>
+ </td>
+ </tr>
+% }
+% }
+% }
+ </table>
+</body>
+</html>
+
+<%args>
+ at reports
+</%args>
+
+<%init>
+my %categories;
+foreach my $report (@reports) {
+ my $data = $report->extra_data;
+ $categories{$data->{category}}->{$data->{subcategory}} = $report;
+}
+</%init>
Modified: Test-Chimps/trunk/lib/Test/Smoke/Report.pm
==============================================================================
--- Test-Chimps/trunk/lib/Test/Smoke/Report.pm (original)
+++ Test-Chimps/trunk/lib/Test/Smoke/Report.pm Fri Jun 23 17:32:32 2006
@@ -4,8 +4,9 @@
use strict;
use Carp;
-use Params::Validate;
+use Params::Validate qw/:all/;
use Test::TAP::HTMLMatrix;
+use YAML::Syck;
=head1 NAME
@@ -40,13 +41,26 @@
=head2 new ARGS
-Creates a new Report. ARGS is a hash whose valid keys are C<model>
-and C<report_text>. C<model> is mandatory and must be an instance
-of C<Test::Tap::Model>. C<report_text> is an optional free-form
-report. If not supplied, it is filled in using
-C<Test::TAP::HTMLMatrix>. Note that if you are using this class in
-conjunction with C<Test::Smoke::Report::Server>, C<report_text>
-should probably be HTML.
+Creates a new Report. ARGS is a hash whose valid keys are:
+
+=over 4
+
+=item * model
+Mandatory and must be an instance of C<Test::Tap::Model>.
+
+=item * report_text
+
+A free-form report. If not supplied, it is filled in using
+C<Test::TAP::HTMLMatrix>, and C<extra_data> will be passed as the
+C<extra> argument to its constructor. Note that if you are using
+this class in conjunction with C<Test::Smoke::Report::Server>,
+C<report_text> should probably be HTML.
+
+=item * extra_data
+
+Extra data to be transmitted with the report.
+
+=back
=cut
@@ -59,10 +73,16 @@
sub _init {
my $self = shift;
- validate(@_,
- { model =>
- { isa => 'Test::TAP::Model'},
- report_text => 0 });
+ validate_with(params => \@_,
+ spec =>
+ { model =>
+ {
+ isa => 'Test::TAP::Model'},
+ report_text => 0,
+ extra_data =>
+ { optional => 1,
+ type => HASHREF } },
+ called => 'The Test::Smoke::Report constructor');
my %args = @_;
@@ -70,7 +90,15 @@
if (defined $args{report_text}) {
$self->{report_text} = $args{report_text};
} else {
- my $v = Test::TAP::HTMLMatrix->new($args{model});
+ my $v;
+ if (defined $args{extra_data}) {
+ $v = Test::TAP::HTMLMatrix->new($args{model},
+ Dump($args{extra}));
+ $self->{extra_data} = $args{extra_data};
+ } else {
+ $v = Test::TAP::HTMLMatrix->new($args{model});
+ $self->{extra_data} = '';
+ }
$self->{report_text} = $v->detail_html;
}
}
@@ -97,6 +125,17 @@
return $self->{report_text};
}
+=head2 extra_data
+
+Accessor for any extra data passed in.
+
+=cut
+
+sub extra_data {
+ my $self = shift;
+ return $self->{extra_data};
+}
+
=head1 AUTHOR
Zev Benjamin, C<< <zev at cpan.org> >>
Modified: Test-Chimps/trunk/lib/Test/Smoke/Report/Client.pm
==============================================================================
--- Test-Chimps/trunk/lib/Test/Smoke/Report/Client.pm (original)
+++ Test-Chimps/trunk/lib/Test/Smoke/Report/Client.pm Fri Jun 23 17:32:32 2006
@@ -84,11 +84,13 @@
sub _init {
my $self = shift;
- validate(@_,
- { reports =>
- { type => ARRAYREF },
- server => 1,
- compress => 0});
+ validate_with(params => \@_,
+ spec =>
+ { reports =>
+ { type => ARRAYREF },
+ server => 1,
+ compress => 0},
+ called => 'The Test::Smoke::Report::Client constructor');
my %args = @_;
$self->{reports} = $args{reports};
Modified: Test-Chimps/trunk/lib/Test/Smoke/Report/Server.pm
==============================================================================
--- Test-Chimps/trunk/lib/Test/Smoke/Report/Server.pm (original)
+++ Test-Chimps/trunk/lib/Test/Smoke/Report/Server.pm Fri Jun 23 17:32:32 2006
@@ -9,11 +9,12 @@
use Digest::MD5 qw<md5_hex>;
use File::Spec;
use Fcntl qw<:DEFAULT :flock>;
-use HTML::Template;
+use HTML::Mason;
use Params::Validate qw<:all>;
use Storable qw<store_fd fd_retrieve freeze>;
use Time::Piece;
use Time::Seconds;
+use YAML::Syck;
use constant PROTO_VERSION => 0.1;
@@ -62,6 +63,11 @@
Burst upload rate allowed (see L<Algorithm::Bucket>). Defaults to
5.
+=item * list_template
+
+Template filename under base_dir/template_dir to use for listing
+smoke reports. Defaults to 'list.tmpl'.
+
=item * max_rate
Maximum upload rate allowed (see L<Algorithm::Bucket>). Defaults
@@ -72,15 +78,26 @@
Maximum size of HTTP POST that will be accepted. Defaults to 3
MiB.
-=item * max_smokes_same_category
+=item * max_smokes_per_subcategory
Maximum number of smokes allowed per category. Defaults to 5.
=item * report_dir
-Directory under basedir where smoke reports will be stored.
+Directory under base_dir where smoke reports will be stored.
Defaults to 'reports'.
+=item * template_dir
+
+Directory under base_dir where html templates will be stored.
+Defaults to 'templates'.
+
+=item * validate_extra
+
+A hash reference in the form accepted by Params::Validate. If
+supplied, this will be used to validate the extra data submitted to
+the server.
+
=back
=cut
@@ -88,7 +105,8 @@
{
no strict 'refs';
our @fields = qw/base_dir bucket_file max_rate max_size
- max_smokes_same_category report_dir/;
+ max_smokes_per_subcategory report_dir
+ template_dir list_template validate_extra/;
foreach my $field (@fields) {
*{$field} =
@@ -108,46 +126,64 @@
sub _init {
my $self = shift;
- my %args = validate(@_,
- { base_dir =>
- { type => SCALAR,
- optional => 0 },
- bucket_file =>
- { type => SCALAR,
- default => 'bucket.dat',
- optional => 1 },
- burst_rate =>
- { type => SCALAR,
- optional => 1,
- default => 5,
- callbacks =>
- { "greater than or equal to 0" =>
- sub { $_[0] >= 0 }} },
- max_rate =>
- { type => SCALAR,
- default => (1 / 30),
- optional => 1,
- callbacks =>
- {"greater than or equal to 0" =>
- sub { $_[0] >= 0 }} },
- max_size =>
- { type => SCALAR,
- default => 2**20 * 3.0,
- optional => 1,
- callbacks =>
- { "greater than or equal to 0" =>
- sub { $_[0] >= 0 }} },
- max_smokes_same_category =>
- { type => SCALAR,
- default => 5,
- optional => 1,
- callbacks =>
- { "greater than or equal to 0" =>
- sub { $_[0] >= 0 }} },
- report_dir =>
- { type => SCALAR,
- default => 'reports',
- optional => 1 } });
+ my %args = validate_with
+ (params => \@_,
+ called => 'The Test::Smoke::Report::Server constructor',
+ spec =>
+ { base_dir =>
+ { type => SCALAR,
+ optional => 0 },
+ bucket_file =>
+ { type => SCALAR,
+ default => 'bucket.dat',
+ optional => 1 },
+ burst_rate =>
+ { type => SCALAR,
+ optional => 1,
+ default => 5,
+ callbacks =>
+ { "greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ list_template =>
+ { type => SCALAR,
+ optional => 1,
+ default => 'list.tmpl' },
+ max_rate =>
+ { type => SCALAR,
+ default => (1 / 30),
+ optional => 1,
+ callbacks =>
+ {"greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ max_size =>
+ { type => SCALAR,
+ default => 2**20 * 3.0,
+ optional => 1,
+ callbacks =>
+ { "greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ max_smokes_per_subcategory =>
+ { type => SCALAR,
+ default => 5,
+ optional => 1,
+ callbacks =>
+ { "greater than or equal to 0" =>
+ sub { $_[0] >= 0 }} },
+ pre_add_hook =>
+ { type => CODEREF,
+ optional => 1 },
+ report_dir =>
+ { type => SCALAR,
+ default => 'reports',
+ optional => 1 },
+ template_dir =>
+ { type => SCALAR,
+ default => 'templates',
+ optional => 1 },
+ validate_extra =>
+ { type => HASHREF,
+ optional => 1 }
+ });
foreach my $key (%args) {
$self->{$key} = $args{$key};
@@ -168,7 +204,7 @@
if ($cgi->param("upload")) {
$self->_process_upload($cgi);
} else {
- $self->_process_listing();
+ $self->_process_listing($cgi);
}
}
@@ -178,7 +214,8 @@
print $cgi->header("text/plain");
$self->_limit_rate($cgi);
- $self->_validate_params($cgi);
+ $self->_validate_params($cgi);
+ $self->_validate_extra($cgi);
$self->_add_report($cgi);
$self->_clean_old_reports($cgi);
@@ -236,6 +273,28 @@
# uncompress_smoke();
}
+sub _validate_extra {
+ my $self = shift;
+ my $cgi = shift;
+
+ my @reports = map { Load($_) } $cgi->param("reports");
+
+ if (defined $self->{validate_extra}) {
+ foreach my $report (@reports) {
+ eval {
+ validate(@{$report->{extra_data}}, $self->{validate_extra});
+ };
+ if ($@) {
+ # XXX: doesn't dump subroutines because we're using YAML::Syck
+ print "This server accepts extra parameters. It's validation ",
+ "string looks like this:\n", Dump($self->{validate_extra});
+ exit;
+ }
+
+ }
+ }
+}
+
sub _add_report {
my $self = shift;
my $cgi = shift;
@@ -265,6 +324,24 @@
# XXX: stub
}
+sub _process_listing {
+ my $self = shift;
+ my $cgi = shift;
+ print $cgi->header("text/html");
+ my @reports = map { bless LoadFile($_), 'Test::Smoke::Report' }
+ glob File::Spec->catfile($self->{base_dir},
+ $self->{report_dir},
+ "*.yml");
+
+ my $interp = HTML::Mason::Interp->new(comp_root =>
+ File::Spec->catfile($self->{base_dir},
+ $self->{template_dir}));
+ $interp->exec(File::Spec->catfile('/' . $self->{list_template}),
+ reports => \@reports);
+
+}
+
+
1;
More information about the Rt-commit
mailing list