#!/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_creatg function is able to create a new
# LFC file with the specified GUID or reset it in the name server.
#
##############################################################################
# meta: proxy=True
# meta: preconfig=../../LFC-config
use strict;
use lfc;
use TestCommon;

my ($name,$res,$err_num,$err_string,$guid);
test_title("lfc-creatg");

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

# initializing $error variable used for detecting test errors (it is set to 1 if any test failed)
my $error = 0;

# checking new file creation with specified GUID
action_title("Checking new file creation with specified GUID");
# defining unique file name with help of current number of seconds since epoch
my $t = time();
$name = "/grid/$vo/perl_creatg_test_$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/perl_creatg_test_$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during file $name creation: Error $err_num ($err_string)");
  $error =1;
} else {
  action_ok();
  remove_file($name);
}

# checking for ability to reset existing file
action_title("Checking for ability to reset existing file");
# defining unique file name with help of current number of seconds since epoch
$t = time();
$name = "/grid/$vo/perl_creatg_test_$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/perl_creatg_test_$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during file $name creation: Error $err_num ($err_string)");
  $error =1;
} else {
  $res = lfc::lfc_creatg($name,$guid,0664);
  if ($res != 0) {
    $err_num = $lfc::serrno;
    $err_string = lfc::sstrerror($err_num);
    action_failed();
    action_err_msg("There was an error during file $name reset (overwriting the existing one): Error $err_num ($err_string)");
    $error =1;
  } else {
  action_ok();
  remove_file($name);
  }
}


# checking the case when a component of path prefix does not exist (ENOENT).
action_title("Checking the case when a component of path prefix does not exist (ENOENT)");
$t = time();
$name = "/grid/$vo/$t/perl_creatg_ENOENT_test_file";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/grid/$vo/perl_creatg_ENOENT_test_file_$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create the file $name while a component of its path prefix did not exist");
  $error = 1;
  remove_file($name);
} else {
  action_ok();
  # 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";
}

# checking the case when path is a null pathname (ENOENT).
action_title("Checking the case when path is a null pathname (ENOENT)");
$t = time();
$name = "";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/grid/$vo/perl_creatg_ENOENT_test_file_$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create the file $name with a null pathname");
  $error = 1;
  remove_file($name);
} else {
  action_ok();
  # 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";
}

# checking the case when file does not exist and write permission on the parent directory is denied (EACCES)
action_title("Checking the case when file does not exist and write permission on the parent directory is denied (EACCES)");
$name = "/perl_creatg_EACCES_test_file_"."$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/grid/$vo/perl_creatg_test_file_$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res == 0) {
  action_failed();
  action_err_msg("The test could create the file $name when the write permission on the parent directory was denied");
  remove_file($name);
  $error = 1;
} else {
  action_ok();
  # 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";
}

# 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)");
# defining unique dir name with help of current number of seconds since epoch
$t = time();
my $dir = "/grid/$vo/perl_creatg_EACCES_test_$t";
$res = lfc::lfc_mkdir($dir,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 $dir creation: Error $err_num ($err_string)");
  $error = 1;
} else {
  $guid = gen_guid();
  $name = $dir."/test_creatg_file";
  # uncomment the line below to check if test prints the proper message in case of failure
  #lfc::lfc_chmod($dir,0755);
  $res = lfc::lfc_creatg($name,$guid,0664);
  if ($res == 0) {
    action_failed();
    action_err_msg("Test could create the file $name when a search permission was denied on a component of its path");
    $error = 1;
    remove_file($name);
  } else {
    action_ok();
    # 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";
  }
  # removing test dir
  remove_dir($dir);
}

# checking the case when file exists and write permission on the file itself is denied (EACCES)
action_title("Checking the case when file exists and write permission on the file itself is denied (EACCES)");
$t = time();
$name = "/grid/$vo/perl_creatg_EACCES_test_file_"."$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0444);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during file $name creation: Error $err_num ($err_string)");
} else {
  # uncomment the line below to check if test prints the proper message in case of failure
  #lfc::lfc_chmod($name,0755);
  $res = lfc::lfc_creatg($name,$guid,0755);
  if ($res == 0) {
    action_failed();
    action_err_msg("The test could reset the file $name when the write permission on the file itself was denied");
    remove_file($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();
    lfc::lfc_chmod($name,0755);
    remove_file($name);
  }
}

# checking the case when specified path is a NULL pointer (EFAULT).
action_title("Checking the case when specified path is a NULL pointer (EFAULT)");
$name = undef;
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/grid/$vo/perl_creatg_EFAULT_test";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0755);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create a file with undefined path value");
  $error = 1;
  remove_file($name);
} else {
  action_ok();
  # 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";
}

# checking the case when GUID is a NULL pointer (EFAULT).
#action_title("Checking the case when GUID is a NULL pointer (EFAULT)");
#$name = "/grid/$vo/perl_creatg_EFAULT_test";
#$guid = undef;
# uncomment the line below to check if test prints the proper message in case of failure
#$guid = gen_guid();
#$res = lfc::lfc_creatg($name,$guid,0755);
#if ($res == 0) {
#  action_failed();
#  action_err_msg("Test could create a file with undefined GUID");
#  $error = 1;
#  remove_file($name);
#} else {
#  action_ok();
#  # 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";
#}

# checking the case when file already exists with a different GUID (EEXIST)
action_title("Checking the case when file exists with a different GUID (EEXIST)");
$t = time();
$name = "/grid/$vo/perl_creatg_EEXIST_test_file_"."$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during file $name creation: Error $err_num ($err_string)");
} else {
  # comment out the line below to check if test prints the proper message in case of failure
  $guid = gen_guid();
  $res = lfc::lfc_creatg($name,$guid,0664);
  if ($res == 0) {
    action_failed();
    action_err_msg("The test could reset the existing file $name with different GUID");
    $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();
  }
  remove_file($name);
}

# checking the case when a component of path prefix is not a directory (ENOTDIR)
action_title("Checking the case when a component of path prefix is not a directory (ENOTDIR)");
# creating a test file which will be a part of the  new dir path
$t = time();
$name = "/grid/$vo/perl_creatg_ENOTDIR_testfile_$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/perl_filerename_test_"."$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res != 0) {
  $err_num = $lfc::serrno;
  $err_string = lfc::sstrerror($err_num);
  action_failed();
  action_err_msg("There was an error during file $name creation: Error $err_num ($err_string)");
  $error =1;
} else {
  # create a file name with a path what includes the file
  my $new_name = $name."/perl_creatg_testfile";
  # uncomment the line below to check if test prints the proper message in case of failure
  #$new_name = "/grid/$vo/perl_creatg_testfile";
  $guid = gen_guid();
  $res = lfc::lfc_creatg($new_name,$guid,0755);
  if ($res == 0) {
    action_failed();
    action_err_msg("Test could create the file $new_name a component of which path prefix is not a directory");
    remove_file($new_name);
    $error = 1;
  } else {
    action_ok();
    # 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";
  }
  remove_file($name);
}

# checking the case when path is an existing directory (EISDIR)
action_title("Checking the case when path is an existing directory (EISDIR)");
$t = time();
$name = "/grid/$vo/perl_creatg_ENOTDIR_testdir_$t";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/perl_creatg_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 dir $name creation: Error $err_num ($err_string)");
  $error =1;
} else {
  $guid = gen_guid();
  $res = lfc::lfc_creatg($name,$guid,0755);
  if ($res == 0) {
    action_failed();
    action_err_msg("Test could create the file $name what was a directory before");
    remove_file($name);
    $error = 1;
  } else {
    action_ok();
    # 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";
    remove_dir($name);
  }
}

# checking the case when the length of the GUID exceeds CA_MAXGUIDLEN (EINVAL)
action_title("Checking the case when the length of the GUID exceeds CA_MAXGUIDLEN (EINVAL)");
$t = time();
$name = "/grid/$vo/perl_creatg_EINVAL_testfile_"."$t";
$guid = gen_guid();
$guid = "$guid"."$t";
#print "name is $name\nGUID is $guid\nits length is ",length($guid),"\n";
#print "\$lfc::CA_MAXGUIDLEN is $lfc::CA_MAXGUIDLEN\n";
# uncomment the line below to check if test prints the proper message in case of failure
#$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create a file with guid length larger than CA_MAXGUIDLEN ($lfc::CA_MAXGUIDLEN)");
  remove_file($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 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_creatg_test_";
while (length($name)<$lfc::CA_MAXPATHLEN+1) { $name = $name.'a' }
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/grid/$vo/perl_creatg_testfile_"."$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0644);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create a file with path name larger than CA_MAXPATHLEN ($lfc::CA_MAXPATHLEN)");
  remove_file($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 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_creatg_testfile_";
while (length($name)<$lfc::CA_MAXNAMELEN+1) { $name = $name.'a' }
$name = "/grid/$vo/".$name;
#print "\$name is $name,length is ",length($name),"\nCA_MAXNAMELEN is $lfc::CA_MAXNAMELEN\n";
# uncomment the line below to check if test prints the proper message in case of failure
#$name = "/grid/$vo/perl_creatg_testfile_"."$t";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0755);
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create a dir with length of path component larger than CA_MAXNAMELEN ($lfc::CA_MAXNAMELEN)");
  remove_file($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 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;
# uncomment the line below to check if test prints the proper message in case of failure
#$ENV{'LFC_HOST'} = $lfc_host;
$name = "/grid/$vo/perl_creatg_SENOSHOST_testfile";
# 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";
$guid = gen_guid();
$res = lfc::lfc_creatg($name,$guid,0664);
# restoring STDERR
open (STDERR,">&COPY_STDERR")|| die "Can't restore STDERR";
if ($res == 0) {
  action_failed();
  action_err_msg("Test could create a file on unknown LFC host ($ENV{'LFC_HOST'})");
  $error = 1;
  remove_file($name);
} else {
  action_ok();
  # 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";
}
# restoring default LFC_HOST environment value
$ENV{'LFC_HOST'} = $lfc_host;

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

