File:  [LON-CAPA] / loncom / metadata_database / lonmetadata_test.pl
Revision 1.5: download - view: text, annotated - select for diffs
Fri Jun 11 19:52:12 2004 UTC (20 years, 5 months ago) by matthew
Branches: MAIN
CVS tags: version_2_9_X, version_2_9_99_0, version_2_9_1, version_2_9_0, version_2_8_X, version_2_8_99_1, version_2_8_99_0, version_2_8_2, version_2_8_1, version_2_8_0, version_2_7_X, version_2_7_99_1, version_2_7_99_0, version_2_7_1, version_2_7_0, version_2_6_X, version_2_6_99_1, version_2_6_99_0, version_2_6_3, version_2_6_2, version_2_6_1, version_2_6_0, version_2_5_X, version_2_5_99_1, version_2_5_99_0, version_2_5_2, version_2_5_1, version_2_5_0, version_2_4_X, version_2_4_99_0, version_2_4_2, version_2_4_1, version_2_4_0, version_2_3_X, version_2_3_99_0, version_2_3_2, version_2_3_1, version_2_3_0, version_2_2_X, version_2_2_99_1, version_2_2_99_0, version_2_2_2, version_2_2_1, version_2_2_0, version_2_1_X, version_2_1_99_3, version_2_1_99_2, version_2_1_99_1, version_2_1_99_0, version_2_1_3, version_2_1_2, version_2_1_1, version_2_1_0, version_2_12_X, version_2_11_X, version_2_11_5_msu, version_2_11_5, version_2_11_4_uiuc, version_2_11_4_msu, version_2_11_4, version_2_11_3_uiuc, version_2_11_3_msu, version_2_11_3, version_2_11_2_uiuc, version_2_11_2_msu, version_2_11_2_educog, version_2_11_2, version_2_11_1, version_2_11_0_RC3, version_2_11_0_RC2, version_2_11_0_RC1, version_2_11_0, version_2_10_X, version_2_10_1, version_2_10_0_RC2, version_2_10_0_RC1, version_2_10_0, version_2_0_X, version_2_0_99_1, version_2_0_2, version_2_0_1, version_2_0_0, version_1_99_3, version_1_99_2, version_1_99_1_tmcc, version_1_99_1, version_1_99_0_tmcc, version_1_99_0, version_1_3_X, version_1_3_3, version_1_3_2, version_1_3_1, version_1_3_0, version_1_2_X, version_1_2_99_1, version_1_2_99_0, version_1_2_1, version_1_2_0, version_1_1_99_5, version_1_1_99_4, version_1_1_99_3, version_1_1_99_2, version_1_1_99_1, loncapaMITrelate_1, language_hyphenation_merge, language_hyphenation, bz6209-base, bz6209, bz5969, bz2851, PRINT_INCOMPLETE_base, PRINT_INCOMPLETE, HEAD, GCI_3, GCI_2, GCI_1, BZ5971-printing-apage, BZ5434-fox, BZ4492-merge, BZ4492-feature_horizontal_radioresponse
lonmetadata:
  Minor changes to &store_metadata, should be a little more readable now.
  &lookup_metadata: added $tablename input parameter, defaults to 'metadata'.
  Implemented &delete_metadata
  Added &update_metadata
lonmetadata_test.pl:
  Added tests for &lookup_metadata, &delete_metadata, and &update_metadata
  Added utility routines &metadata_do_not_match, &metadata_mismatch_error,
  &testrecords, &build_test_table.

#!/usr/bin/perl -w
# The LearningOnline Network with CAPA
#
# $Id: lonmetadata_test.pl,v 1.5 2004/06/11 19:52:12 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA 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 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA 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 LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#
######################################################################
use strict;

use DBI;
use LONCAPA::lonmetadata();
use Test::Simple tests => 7;

##
##  Note: The root password to my MySQL server is shown below.
##  Access is only allowed from localhost so it should be okay.
##  Now if you will excuse me I have to change the password on my luggage.
##
my $supersecretpassword = '123';  # shhhh

ok(&create_test_db(),'database creation');
ok(&test_creation(),'table creation');
ok(&test_named_creation(),'named table creation');
ok(&test_inserts(),'insert test');
ok(&test_retrieval(),'retrieval test');
ok(&test_delete(),'delete test');
ok(&test_update(),'update test');

exit;

#####################################################################
#####################################################################
##
##  Tests live down below
##
#####################################################################
#####################################################################
sub create_test_db {
    my $dbh = DBI->connect("DBI:mysql:test","root",$supersecretpassword,
                           { RaiseError =>0,PrintError=>0});
    if (! defined($dbh)) {
        return 0;
    }
    my $request = 'DROP DATABASE IF EXISTS lonmetatest';
    $dbh->do($request);
    $request = 'CREATE DATABASE lonmetatest';
    $dbh->do($request);
    if ($dbh->err) {
        return 0;
    } else {
        return 1;
    }
    $dbh->disconnect();
}

sub test_creation {
    my $dbh = DBI->connect("DBI:mysql:lonmetatest","root",$supersecretpassword,
                           { RaiseError =>0,PrintError=>0});
    my $request = &LONCAPA::lonmetadata::create_metadata_storage();
    $dbh->do($request);
    if ($dbh->err) {
        $dbh->disconnect();
        return 0;
    } else {
        $dbh->disconnect();
        return 1;
    }
}

sub test_named_creation {
    my $request = 
             &LONCAPA::lonmetadata::create_metadata_storage('nonmetadata');
    my $dbh = DBI->connect("DBI:mysql:lonmetatest","root",$supersecretpassword,
                           { RaiseError =>0,PrintError=>0});
    $dbh->do($request); # Create the table, only return 0 if we cannot.
    if ($dbh->err) {
        $dbh->disconnect();
        return 0;
    }
    $dbh->do('DROP TABLE nonmetadata'); # This will generate an error if the
                                        # table does not exist
    if ($dbh->err) {
        $dbh->disconnect();
        return 0;
    }
    return 1;
}

sub test_inserts {
    my @TestRecords = &testrecords();
    my $tablename = 'metadatatest';
    my $dbh = DBI->connect("DBI:mysql:lonmetatest","root",$supersecretpassword,
                           { RaiseError =>1,PrintError=>1});
    # Create the table
    my $request = &LONCAPA::lonmetadata::create_metadata_storage($tablename);
    $dbh->do($request);
    if ($dbh->err) {
        $dbh->disconnect();
        warn "Unable to create table for test";
        return 0;
    }
    # Store the sample records
    foreach my $data (@TestRecords) {
        my ($count,$error) = &LONCAPA::lonmetadata::store_metadata($dbh,
                                                                   $tablename,
                                                                   $data);
        if (! $count) {
            warn $error;
            return 0;
        }
    }
    $dbh->do('DROP TABLE '.$tablename);
    $dbh->disconnect();
    return 1;
}

sub test_retrieval {
    &LONCAPA::lonmetadata::clear_sth();
    my $tablename = 'metadatatest';
    my $dbh = DBI->connect("DBI:mysql:lonmetatest","root",$supersecretpassword,
                           { RaiseError =>0,PrintError=>0});
    if (! &build_test_table($dbh,$tablename)) {
        warn "Unable to build test table\n";
        return 0;
    }
    # Retrieve records
    my $count=0;
    my @TestRecords = &testrecords();
    foreach my $data (@TestRecords) {
        my ($error,$row) = &LONCAPA::lonmetadata::lookup_metadata
                              ($dbh,' url='.$dbh->quote($data->{'url'}),
                               undef,$tablename);
        if ($error) {
            warn "Retrieval error for item $count\n";
            return 0;
        }
        my %fromdb = &LONCAPA::lonmetadata::metadata_col_to_hash(@{$row->[0]});
        if (&metadata_do_not_match($data,\%fromdb)) {
            warn(&metadata_mismatch_error.$/);
            return 0;
        }
        $count++;
    }
    #
    $dbh->do('DROP TABLE '.$tablename);
    $dbh->disconnect();
    return 1;
}

sub test_delete {
    my $tablename = 'metadatatest';
    my $dbh = DBI->connect("DBI:mysql:lonmetatest","root",$supersecretpassword,
                           { RaiseError =>0,PrintError=>0});
    if (! &build_test_table($dbh,$tablename)) {
        return 0;
    }
    my @TestRecords = &testrecords();
    foreach my $record (@TestRecords) {
        my $error = &LONCAPA::lonmetadata::delete_metadata($dbh,$tablename,
                                                           $record->{'url'});
        if ($error) {
            warn $error;
            return 0;
        }
        # Verify delete has taken place
        my $row;
        ($error,$row) = &LONCAPA::lonmetadata::lookup_metadata
                              ($dbh,' url='.$dbh->quote($record->{'url'}),
                               undef,$tablename);
        if (defined($row) && ref($row) eq 'ARRAY' && defined($row->[0])) {
            # We retrieved the record we just deleted.  This is BAD.
            return 1;
        }
    }
    $dbh->do('DROP TABLE '.$tablename);
    $dbh->disconnect();
    return 1;
}

sub test_update {
    my $tablename = 'metadatatest';
    my $dbh = DBI->connect("DBI:mysql:lonmetatest","root",$supersecretpassword,
                           { RaiseError =>0,PrintError=>0});
    if (! &build_test_table($dbh,$tablename)) {
        return 0;
    }
    my @TestRecords = &testrecords();
    foreach my $record (@TestRecords) {
        $record->{'title'}.= 'newtitle';
        my $error = &LONCAPA::lonmetadata::update_metadata
            ($dbh,$tablename,
             { url   => $record->{'url'},
               title => $record->{'title'} });
        if ($error) {
            warn $error.$/;
            return 0;
        }
        my $row;
        ($error,$row) = &LONCAPA::lonmetadata::lookup_metadata
                    ($dbh,' url='.$dbh->quote($record->{'url'}),
                     undef,$tablename);
        if ($error) {
            warn $error.$/;
            return 0;
        }
        my %fromdb = &LONCAPA::lonmetadata::metadata_col_to_hash(@{$row->[0]});
        if (&metadata_do_not_match($record,\%fromdb)) {
            warn(&metadata_mismatch_error.$/);
            return 0;
        }
    }
    #
    # Now test by updating a resource that does not have an entry.
    my @NewThings = (
            { url => 'm/b/h/test100' },
            { url => "m/b/h/t'e\"st101" },
            { title => 'test document 102',
              author => 'matthew',
              subject => 'subject 1',
              url => 'm/b/h/test102',
              keywords => 'key word',
              version => '1.4',
              notes => 'note note note',
              abstract => 'probably' },);
    foreach my $record (@NewThings) {
        print "testing ".$record->{'url'}.$/;
        my $error = &LONCAPA::lonmetadata::update_metadata
            ($dbh,$tablename,$record);
        if ($error) {
            warn $error.$/;
            return 0;
        }
        my $row;
        ($error,$row) = &LONCAPA::lonmetadata::lookup_metadata
                    ($dbh,' url='.$dbh->quote($record->{'url'}),
                     undef,$tablename);
        if ($error) {
            warn $error.$/;
            return 0;
        }
        my %fromdb = &LONCAPA::lonmetadata::metadata_col_to_hash(@{$row->[0]});
        if (&metadata_do_not_match($record,\%fromdb)) {
            warn(&metadata_mismatch_error.$/);
            return 0;
        }
    }
    $dbh->do('DROP TABLE '.$tablename);
    $dbh->disconnect();
    return 1;
}

##################################################################
##################################################################
sub build_test_table {
    my ($dbh,$tablename) = @_;
    &LONCAPA::lonmetadata::clear_sth();
    if (! defined($tablename)) {
        warn "No table name specified in build_test_table.\n";
        return 0;
    }
    my @TestRecords = &testrecords();
    # Create the table
    my $request = &LONCAPA::lonmetadata::create_metadata_storage($tablename);
    $dbh->do($request);
    if ($dbh->err) {
        $dbh->disconnect();
        warn "Unable to create table for test";
        return 0;
    }
    # Store the sample records 
    foreach my $data (@TestRecords) {
        my ($count,$error) = &LONCAPA::lonmetadata::store_metadata($dbh,
                                                                   $tablename,
                                                                   $data); 
        if (! $count) {
            warn $error;
            return 0;
        }
    }
    return 1;
}

##################################################################
##################################################################
sub testrecords {
    return (
            { url => 'm/b/h/test1' },
            { url => "m/b/h/t'e\"st1" },
            { title => 'test document 1',
              author => 'matthew',
              subject => 'subject 1',
              url => 'm/b/h/test2',
              keywords => 'key word',
              version => '1.4',
              notes => 'note note note',
              abstract => 'probably',
              mime => 'none',
              language => 'english',
              creationdate =>'',
              lastrevisiondate =>'',
              owner => 'hallmat3',
              copyright => 'default',
              dependencies => undef,
              modifyinguser => 'hallmat3',
              authorspace => 'hallmat3',
              lowestgradelevel =>'1',
              highestgradelevel => 16,
              standards => 'Delaware Required Instruction Program',
              count => '2544444',
              course => '4',
              course_list => 'course 1, course 2, course 3, course 4',
              goto => '1',
              goto_list =>'m/b/h/test1',
              comefrom => '0',
              comefrom_list =>'',
              sequsage => '1',
              sequsage_list =>'mbhtest.sequence',
              stdno => '0',
              stdno_list => '',
              avetries => '0.0',
              avetries_list =>'',
              difficulty =>'',
              difficulty_list => '',
              clear => '5',
              technical => '4',
              correct => '3',
              helpful => '2',
              depth => '5',
              hostname =>'6',
          },
            );
}

##################################################################
##################################################################
{

    my $error;

sub metadata_do_not_match {
    my ($orig,$fromdb) = @_;
    my %checkedfields;
    my $url = $orig->{'url'};
    foreach my $field (keys(%$orig)){
        #
        # Make sure the field exists
        if (! exists($fromdb->{$field})) {
            $error = 'url='.$url.': field '.$field.' missing.';
            return 1;
        }
        #
        # Make sure each field matches
        my ($old,$new) = ($orig->{$field},$fromdb->{$field});
        if (! defined($new) && ! defined($old)) {
            next;
        } elsif (! defined($new) && defined($old)){
            if ($old eq '') {
                next; # This is okay, we treat undef and '' equivalently.
            } else {
                $error  = 'url='.$url.' mismatch on '.$field.$/;
                $error .= 'old="'.$orig->{'field'}.'" new=undef'.$/;
                return 1;
            }
        } elsif (defined($new) && ! defined($old)) {
            if ($new eq '') {
                next; # This is okay, we treat undef and '' equivalently.
            } else {
                $error  = 'url='.$url.' mismatch on '.$field.$/;
                $error .= 'old=undef new="'.$new.'"'.$/;
                return 1;
            }
        } elsif (($old ne $new)) {
            if ($field =~ /date$/  && $old eq '' && 
                $new eq '0000-00-00 00:00:00') {
                # '' is the same as '0' for dates
                next;
            }
            if ($old =~ /\d*\.?\d*/) {
                next if (abs($old - $new) < 0.000001);
            }
            #
            $error  = 'url='.$url.' mismatch on '.$field.$/;
            $error .= 'old="'.$old.'" new="'.$new.'"';
            return 1;
        }
        #
        $checkedfields{$field}++;
    }
    foreach my $k (keys(%{$fromdb})) {
        next if (exists($checkedfields{$k}));
        next if (! defined($fromdb->{$k}));
        next if ($fromdb->{$k} eq '' ||
                 $fromdb->{$k} eq '0' ||
                 $fromdb->{$k} eq '0000-00-00 00:00:00');
        $error = 'new has field '.$k.' which old does not have.  '.
            'value = '.$fromdb->{$k};
        return 1;
    }
    return 0;
}

sub metadata_mismatch_error {
    return $error;
}

}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>