#!/usr/bin/perl -w
##############################################################################
# Copyright (c) Members of the EGEE Collaboration. 2010.
# See http://www.eu-egee.org/partners/ for details on the copyright
# holders.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS
# OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
##############################################################################
#
# AUTHORS: Nikolay.Kutovskiy@jinr.ru
#
# DESCRIPTION:
# This test checks if the perl API lfc_setcomment function is able to add or
# replace a comment associated with a LFC file/directory in the name server.
#
##############################################################################
# meta: proxy=True
# meta: preconfig=../../LFC-config
use strict;
use lfc;
use TestCommon;

my ($name,$res,$err_num,$err_string,$comment);

test_title("lfc-setcomment");

# defining VO name
my $vo = $ENV{VO};

# initializing $error variable used for detecting test errors
my $error = 0;

# checking the ability to add a comment to directory
action_title("Checking the ability to add a comment to directory");
my $t = time();
$name = "/grid/$vo/perl_setcomment_testdir_$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/perl_setcomment_testdir_$t";
$res = lfc::lfc_mkdir($name,0755);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during directory $name creation: Error $err_num ($err_string)");
  $error = 1;
} else {
  $comment = "test comment";
  $res = lfc::lfc_setcomment($name,$comment);
  if ($res != 0) {
    $err_num = $lfc::serrno;
    $err_string = lfc::sstrerror($err_num);
    action_failed();
    action_err_msg("There was an error during setting a comment for  directory $name: Error $err_num ($err_string)");
    $error = 1;
  } else {
    action_ok();
  }
  remove_dir($name);
}

# checking the ability to replace an existing comment on directory
action_title("Checking the ability to replace an existing comment on directory");
$t = time();
$name = "/grid/$vo/perl_setcomment_testdir_$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/perl_setcomment_testdir_$t";
$res = lfc::lfc_mkdir($name,0755);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during directory $name creation: Error $err_num ($err_string)");
  $error = 1;
} else {
  $comment = "test comment";
  my $new_comment = "new test comment";
  $res = lfc::lfc_setcomment($name,$comment);
  if ($res != 0) {
    $err_num = $lfc::serrno;
    $err_string = lfc::sstrerror($err_num);
    action_failed();
    action_err_msg("There was an error during setting a comment for  directory $name: Error $err_num ($err_string)");
    $error = 1;
  } else {
    $res = lfc::lfc_setcomment($name,$new_comment);
    if ($res != 0) {
      $err_num = $lfc::serrno;
      $err_string = lfc::sstrerror($err_num);
      action_failed();
      action_err_msg("There was an error during setting a comment for  directory $name: Error $err_num ($err_string)");
      $error = 1;
    } else {
      # reading the new comment
      my $bufspec =  "x".($lfc::CA_MAXCOMMENTLEN+1);
      my $buffer = pack($bufspec);
      $res = lfc::lfc_getcomment($name,$buffer);
      if ($res != 0) {
        $err_num = $lfc::serrno;
        $err_string = lfc::sstrerror($err_num);
        print "Problem while reading the comment for $name: Error $err_num ($err_string)\n";
      } else {
        $comment = unpack("Z*", $buffer);
        if ($comment ne $new_comment) {
          action_failed();
          action_err_msg("New comment and the old one do not match: new comment was $new_comment but the got one is $comment");
        } else {
          action_ok();
        }
      }  
    }
  }
  remove_dir($name);
}


# checking the case when specified path does not exist (ENOENT)
action_title("Checking the case when specified path does not exist (ENOENT)");
$t = time();
$name = "/grid/$vo/perl_setcomment_ENOENT_test_$t";
$comment = "test comment";
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on non-existing dir $name");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error $err_num ($err_string)\n";
  action_ok();
}

# checking the case when path is a null pathname (ENOENT)
action_title("Checking the case when path is a null pathname (ENOENT)");
$name = "";
$comment = "test comment";
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on dir when its path was a null pathname");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error $err_num ($err_string)\n";
  action_ok();
}

## checking the case when a search permission is denied on a component of path prefix (EACCES)
#action_title("Checking the case when a search permission is denied on a component of path prefix (EACCES)");
#$t = time();
#$name = "/grid/$vo/perl_setcomment_EACCES_test_$t";
#$res = lfc::lfc_mkdir($name,0644);
#if ($res != 0) {
#  $err_num = $lfc::serrno;
#  $err_string = lfc::sstrerror($err_num);
#  action_failed();
#  action_err_msg("There was an error during directory $name creation: Error $err_num ($err_string)");
#  $error = 1;
#} else {
#  # uncomment the line below to check if test prints the proper message in case of failure
#  #lfc::lfc_chmod($name,0755);
#  $comment = "test comment";
#  $res = lfc::lfc_setcomment($name,$comment);
#  if ($res == 0) {
#    action_failed();
#    action_err_msg("Test could set a comment on dir $name when a search permission was denied on a component of its path");
#    $error = 1;
#  } else {
#    # uncomment three lines below to see if the error is correct
#    $err_num = $lfc::serrno;
#    $err_string = lfc::sstrerror($err_num);
#    print "Error: $err_num ($err_string)\n";
#    action_ok();
#  }
#  # removing test dir
#  remove_dir($name);
#}

## checking the case when a write permission on directory itself is denied (EACCES)
#action_title("Checking the case when a write permission on directory itself is denied (EACCES)");
#$t = time();
#$name = "/grid/$vo/perl_setcomment_EACCES_test_$t";
#$res = lfc::lfc_mkdir($name,0444);
#if ($res != 0) {
#  $err_num = $lfc::serrno;
#  $err_string = lfc::sstrerror($err_num);
#  action_failed();
#  action_err_msg("There was an error during directory $name creation: Error $err_num ($err_string)");
#  $error = 1;
#} else {
#  # uncomment the line below to check if test prints the proper message in case of failure
#  #lfc::lfc_chmod($name,0755);
#  $comment = "test comment";
#  $res = lfc::lfc_setcomment($name,$comment);
#  if ($res == 0) {
#    action_failed();
#    action_err_msg("Test could set a comment on dir $name when a write permission on a directory itself was denied");
#    $error = 1;
#  } else {
#    # uncomment three lines below to see if the error is correct
#    $err_num = $lfc::serrno;
#    $err_string = lfc::sstrerror($err_num);
#    print "Error: $err_num ($err_string)\n";
#    action_ok();
#  }
#  # removing test dir
#  remove_dir($name);
#}

# checking the case when a path is NULL pointer (EFAULT).
action_title("Checking the case when a path is NULL pointer (EFAULT)");
$name = undef;
$comment = "test comment";
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on dir $name when a path was a NULL pointer");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error $err_num ($err_string)\n";
  action_ok();
}

action_title("Checking the case when a comment is NULL pointer (EFAULT)");
$name = "/grid/$vo/perl_setcomment_EFAULT_test";
$comment = undef;
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on dir $name when a comment was a NULL pointer");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error $err_num ($err_string)\n";
  action_ok();
}

# checking the case when the length of comment exceeds CA_MAXCOMMENTLEN (EINVAL)
action_title("Checking the case when the length of comment exceeds CA_MAXCOMMENTLEN (EINVAL)");
$name = "/grid/$vo";
$comment = "test_comment";
while (length($comment)<$lfc::CA_MAXCOMMENTLEN+1) { $comment = $comment.'a' }
#print "comment: $comment\n";
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on dir $name while the length of comment exceeds CA_MAXCOMMENTLEN ($lfc::CA_MAXCOMMENTLEN)");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error $err_num ($err_string)\n";
  action_ok();
}

# checking the case when the length of specified path exceeds CA_MAXPATHLEN (ENAMETOOLONG)
action_title("Checking the case when the length of specified path exceeds CA_MAXPATHLEN (ENAMETOOLONG)");
$name = "/grid/$vo/perl_setcomment_test_";
while (length($name)<$lfc::CA_MAXPATHLEN+1) { $name = $name.'a' }
$comment = "test_comment";
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on dir with path length larger than CA_MAXPATHLEN ($lfc::CA_MAXPATHLEN)");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error: $err_num ($err_string)\n";
  action_ok();
}

# checking the case when the length of path component exceeds CA_MAXNAMELEN (ENAMETOOLONG)
action_title("Checking the case when the length of path component exceeds CA_MAXNAMELEN (ENAMETOOLONG)");
$name = "perl_setcomment_test_";
while (length($name)<$lfc::CA_MAXNAMELEN+1) { $name = $name.'a' }
$name = "/grid/$vo/".$name;
$comment = "test_comment";
$res = lfc::lfc_setcomment($name,$comment);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on directory with length of path component larger than CA_MAXNAMELEN ($lfc::CA_MAXNAMELEN)");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error: $err_num ($err_string)\n";
  action_ok();
}

# checking the case when LFC host is unknown
action_title("Checking the case when LFC host is unknown (SENOSHOST)");
# retrieving default value for LFC_HOST env variable
my $lfc_host = $ENV{'LFC_HOST'};
#print "LFC_HOST is $lfc_host\n";
#changing the value for LFC_HOST environment variable
$t = time();
$ENV{'LFC_HOST'} = "random_lfc_host_$t";
$name = "/grid/$vo/perl_setcomment_SENOSHOST_test";
# temporary closing STDERR to prevent error message to be displayed during that subtest execution
open (COPY_STDERR,">&STDERR");
close(STDERR) or die "Can't close STDERR: $!\n";
$comment = "test_comment";
$res = lfc::lfc_setcomment($name,$comment);
# restoring STDERR
open (STDERR,">&COPY_STDERR")|| die "Can't restore STDERR";
if ($res == 0) {
  action_failed();
  action_err_msg("Test could set a comment on dir on unknown LFC host ($ENV{'LFC_HOST'})");
  $error = 1;
} else {
  # uncomment three lines below to see if the error is correct
  #$err_num = $lfc::serrno;
  #$err_string = lfc::sstrerror($err_num);
  #print "Error $err_num ($err_string)\n";
  action_ok();
}
# restoring default LFC_HOST environment value
$ENV{'LFC_HOST'} = $lfc_host;

# print the test final status
if ($error) {
  test_failed();
} else {
  test_passed();
}

