+++ /dev/null
-package t::lib::TestBuilder;
-
-use Modern::Perl;
-use Koha::Database;
-use String::Random;
-
-
-my $gen_type = {
- tinyint => \&_gen_int,
- smallint => \&_gen_int,
- mediumint => \&_gen_int,
- integer => \&_gen_int,
- bigint => \&_gen_int,
-
- float => \&_gen_real,
- decimal => \&_gen_real,
- double_precision => \&_gen_real,
-
- timestamp => \&_gen_date,
- datetime => \&_gen_date,
- date => \&_gen_date,
-
- char => \&_gen_text,
- varchar => \&_gen_text,
- tinytext => \&_gen_text,
- text => \&_gen_text,
- mediumtext => \&_gen_text,
- longtext => \&_gen_text,
-
- set => \&_gen_set_enum,
- enum => \&_gen_set_enum,
-
- tinyblob => \&_gen_blob,
- mediumblob => \&_gen_blob,
- blob => \&_gen_blob,
- longblob => \&_gen_blob,
-};
-
-our $default_value = {
- UserPermission => {
- borrowernumber => {
- surname => 'my surname',
- address => 'my adress',
- city => 'my city',
- branchcode => {
- branchcode => 'cB',
- branchname => 'my branchname',
- },
- categorycode => {
- categorycode => 'cC',
- hidelostitems => 0,
- category_type => 'A',
- default_privacy => 'default',
- },
- privacy => 1,
- },
- module_bit => {
- module_bit => {
- bit => '10',
- },
- code => 'my code',
- },
- code => undef,
- },
-};
-$default_value->{UserPermission}->{code} = $default_value->{UserPermission}->{module_bit};
-
-
-sub new {
- my ($class) = @_;
- my $self = {};
- bless( $self, $class );
-
- $self->schema( Koha::Database->new()->schema );
- $self->schema->txn_begin();
- $self->schema->storage->sql_maker->quote_char('`');
- return $self;
-}
-
-sub schema {
- my ($self, $schema) = @_;
-
- if( defined( $schema ) ) {
- $self->{schema} = $schema;
- }
- return $self->{schema};
-}
-
-sub clear {
- my ($self, $params) = @_;
- my $source = $self->schema->resultset( $params->{source} );
- return $source->delete_all();
-}
-
-sub build {
- my ($self, $params) = @_;
- my $source = $params->{source} || return;
- my $value = $params->{value};
- my $only_fk = $params->{only_fk} || 0;
-
- my $col_values = $self->_buildColumnValues({
- source => $source,
- value => $value,
- });
-
- my $data;
- my $foreign_keys = $self->_getForeignKeys( { source => $source } );
- for my $fk ( @$foreign_keys ) {
- my $fk_value;
- my $col_name = $fk->{keys}->[0]->{col_name};
- if( ref( $col_values->{$col_name} ) eq 'HASH' ) {
- $fk_value = $col_values->{$col_name};
- }
- elsif( defined( $col_values->{$col_name} ) ) {
- next;
- }
-
- my $fk_row = $self->build({
- source => $fk->{source},
- value => $fk_value,
- });
-
- my $keys = $fk->{keys};
- for my $key( @$keys ) {
- $col_values->{ $key->{col_name} } = $fk_row->{ $key->{col_fk_name} };
- $data->{ $key->{col_name} } = $fk_row;
- }
- }
-
- my $new_row;
- if( $only_fk ) {
- $new_row = $col_values;
- }
- else {
- $new_row = $self->_storeColumnValues({
- source => $source,
- values => $col_values,
- });
- }
- $new_row->{_fk} = $data if( defined( $data ) );
- return $new_row;
-}
-
-sub _formatSource {
- my ($params) = @_;
- my $source = $params->{source};
- $source =~ s|(\w+)$|$1|;
- return $source;
-}
-
-sub _buildColumnValues {
- my ($self, $params) = @_;
- my $source = _formatSource( { source => $params->{source} } );
- my $value = $params->{value};
-
- my $col_values;
- my @columns = $self->schema->source($source)->columns;
- my %unique_constraints = $self->schema->source($source)->unique_constraints();
-
- my $values_ok = 0;
- my $at_least_one_constraint_failed;
-
- while ( not $values_ok ) {
-
- $at_least_one_constraint_failed = 0;
- # generate random values
- for my $col_name( @columns ) {
- my $col_value = $self->_buildColumnValue({
- source => $source,
- column_name => $col_name,
- value => $value,
- });
- $col_values->{$col_name} = $col_value if( defined( $col_value ) );
- }
-
- # If default values are set, maybe the data exist in the DB
- # But no need to wait for another value
- last if exists( $default_value->{$source} );
-
- if ( scalar keys %unique_constraints > 0 ) {
-
- # verify the data would respect each unique constraint
- foreach my $constraint (keys %unique_constraints) {
-
- my $condition;
- my @constraint_columns = $unique_constraints{$constraint};
- # loop through all constraint columns and build the condition
- foreach my $constraint_column ( @constraint_columns ) {
- # build the filter
- $condition->{ $constraint_column } =
- $col_values->{ $constraint_column };
- }
-
- my $count = $self->schema
- ->resultset( $source )
- ->search( $condition )
- ->count();
- if ( $count > 0 ) {
- $at_least_one_constraint_failed = 1;
- # no point checking more stuff, exit the loop
- last;
- }
- }
-
- if ( $at_least_one_constraint_failed ) {
- $values_ok = 0;
- } else {
- $values_ok = 1;
- }
-
- } else {
- $values_ok = 1;
- }
- }
- return $col_values;
-}
-
-# Returns [ {
-# rel_name => $rel_name,
-# source => $table_name,
-# keys => [ {
-# col_name => $col_name,
-# col_fk_name => $col_fk_name,
-# }, ... ]
-# }, ... ]
-sub _getForeignKeys {
- my ($self, $params) = @_;
- my $source = $self->schema->source( $params->{source} );
-
- my @foreign_keys = ();
- my @relationships = $source->relationships;
- for my $rel_name( @relationships ) {
- my $rel_info = $source->relationship_info($rel_name);
- if( $rel_info->{attrs}->{is_foreign_key_constraint} ) {
- my $rel = {
- rel_name => $rel_name,
- source => $rel_info->{source},
- };
-
- my @keys = ();
- while( my ($col_fk_name, $col_name) = each(%{$rel_info->{cond}}) ) {
- $col_name =~ s|self.(\w+)|$1|;
- $col_fk_name =~ s|foreign.(\w+)|$1|;
- push @keys, {
- col_name => $col_name,
- col_fk_name => $col_fk_name,
- };
- }
- $rel->{keys} = \@keys;
-
- push @foreign_keys, $rel;
- }
- }
- return \@foreign_keys;
-}
-
-sub _storeColumnValues {
- my ($self, $params) = @_;
- my $source = $params->{source};
- my $col_values = $params->{values};
-
- my $new_row;
- eval {
- $new_row = $self->schema->resultset($source)->update_or_create($col_values);
- };
- die "$source - $@\n" if ($@);
-
- eval {
- $new_row = { $new_row->get_columns };
- };
- warn "$source - $@\n" if ($@);
- return $new_row;
-}
-
-sub _buildColumnValue {
- my ($self, $params) = @_;
- my $source = $params->{source};
- my $value = $params->{value};
- my $col_name = $params->{column_name};
- my $col_info = $self->schema->source($source)->column_info($col_name);
-
- my $col_value;
- if( exists( $value->{$col_name} ) ) {
- $col_value = $value->{$col_name};
- }
- elsif( exists( $default_value->{$source}->{$col_name} ) ) {
- $col_value = $default_value->{$source}->{$col_name};
- }
- elsif( not $col_info->{default_value} and not $col_info->{is_auto_increment} and not $col_info->{is_foreign_key} ) {
- eval {
- my $data_type = $col_info->{data_type};
- $data_type =~ s| |_|;
- $col_value = $gen_type->{$data_type}->( $self, { info => $col_info } );
- };
- die "The type $col_info->{data_type} is not defined\n" if ($@);
- }
- return $col_value;
-}
-
-
-sub _gen_int {
- my ($self, $params) = @_;
- my $data_type = $params->{info}->{data_type};
-
- my $max = 1;
- if( $data_type eq 'tinyint' ) {
- $max = 127;
- }
- elsif( $data_type eq 'smallint' ) {
- $max = 32767;
- }
- elsif( $data_type eq 'mediumint' ) {
- $max = 8388607;
- }
- elsif( $data_type eq 'integer' ) {
- $max = 2147483647;
- }
- elsif( $data_type eq 'bigint' ) {
- $max = 9223372036854775807;
- }
- return int( rand($max+1) );
-}
-
-sub _gen_real {
- my ($self, $params) = @_;
- my $max = 10 ** 38;
- if( defined( $params->{info}->{size} ) ) {
- $max = 10 ** ($params->{info}->{size}->[0] - $params->{info}->{size}->[1]);
- }
- return rand($max) + 1;
-}
-
-sub _gen_date {
- my ($self, $params) = @_;
- return $self->schema->storage->datetime_parser->format_datetime(DateTime->now());
-}
-
-sub _gen_text {
- my ($self, $params) = @_;
- # From perldoc String::Random
- # max: specify the maximum number of characters to return for * and other
- # regular expression patters that don't return a fixed number of characters
- my $regex = '[A-Za-z][A-Za-z0-9_]*';
- my $size = $params->{info}{size};
- if ( defined $size and $size > 1 ) {
- $size--;
- } elsif ( defined $size and $size == 1 ) {
- $regex = '[A-Za-z]';
- }
- my $random = String::Random->new( max => $size );
- return $random->randregex($regex);
-}
-
-sub _gen_set_enum {
- my ($self, $params) = @_;
- return $params->{info}->{extra}->{list}->[0];
-}
-
-sub _gen_blob {
- my ($self, $params) = @_;;
- return 'b';
-}
-
-
-sub DESTROY {
- my $self = shift;
- $self->schema->txn_rollback();
-}
-
-
-=head1 NAME
-
-t::lib::TestBuilder.pm - Koha module to simplify the writing of tests
-
-=head1 SYNOPSIS
-
- use t::lib::TestBuilder;
-
-Koha module to insert the foreign keys automatically for the tests
-
-=head1 DESCRIPTION
-
-This module allows to insert automatically an entry in the database. All the database changes are wrapped in a transaction.
-The foreign keys are created according to the DBIx::Class schema.
-The taken values are the values by default if it is possible or randomly generated.
-
-=head1 FUNCTIONS
-
-=head2 new
-
- $builder = t::lib::TestBuilder->new()
-
-Constructor - Begins a transaction and returns the object TestBuilder
-
-=head2 schema
-
- $schema = $builder->schema
-
-Getter - Returns the schema of DBIx::Class
-
-=head2 clear
-
- $builder->clear({ source => $source_name })
-
-=over
-
-=item C<$source_name> is the name of the source in the DBIx::Class schema (required)
-
-=back
-
-Clears all the data of this source (database table)
-
-=head2 build
-
- $builder->build({
- source => $source_name,
- value => $value,
- only_fk => $only_fk,
- })
-
-=over
-
-=item C<$source_name> is the name of the source in the DBIx::Class schema (required)
-
-=item C<$value> is the values for the entry (optional)
-
-=item C<$only_fk> is a boolean to indicate if only the foreign keys are created (optional)
-
-=back
-
-Inserts an entry in the database by instanciating all the foreign keys.
-The values can be specified, the values which are not given are default values if they exists or generated randomly.
-Returns the values of the entry as a hashref with an extra key : _fk which contains all the values of the generated foreign keys.
-
-=head1 AUTHOR
-
-Yohann Dufour <yohann.dufour@biblibre.com>
-
-=head1 COPYRIGHT
-
-Copyright 2014 - Biblibre SARL
-
-=head1 LICENSE
-
-This file is part of Koha.
-
-Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
-
-Koha is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License along with Koha; if not, see <http://www.gnu.org/licenses>.
-
-=cut
-
-1;