From a03f6086798a871baca6178c94590c9602f6971c Mon Sep 17 00:00:00 2001 From: Mason James Date: Sat, 3 Oct 2015 02:08:02 +1300 Subject: [PATCH] Revert "Bug 14256: Check for unique constraint to regenerate random data" This reverts commit 0bac7826012b3536bfa62bf2fc1adee91da55b26. --- t/lib/TestBuilder.pm | 456 ------------------------------------------- 1 file changed, 456 deletions(-) delete mode 100644 t/lib/TestBuilder.pm diff --git a/t/lib/TestBuilder.pm b/t/lib/TestBuilder.pm deleted file mode 100644 index 7814df380f..0000000000 --- a/t/lib/TestBuilder.pm +++ /dev/null @@ -1,456 +0,0 @@ -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 - -=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 . - -=cut - -1; -- 2.39.5