From: B. N. P. <poo...@in...> - 2008-07-31 12:57:33
|
Hi, I have developed test cases for sync_file_range() system call which will do the basic sanity (error) checking for the system call. These tests have to be run on 2.6.17 kernel and above. The test cases have been currently tested only on x86 and x86_64 architecture. Also, I have hard coded the system call number in the test case for review purposes and will be later on moving it to linux_syscall_numbers.h file in the LTP framework. Please review the test cases and provide your comments so that I can improve the same. Thanks, Poornima. /****************************************************************************** * syncfilerange01.c * Copyright (c) International Business Machines Corp., 2008 * Email: bnp...@in... *****************************************************************************/ /******************************************************************************/ /* */ /* This program 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. */ /* */ /* This program 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 this program; if not, write to the Free Software */ /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* */ /******************************************************************************/ /***************************************************************************** * TEST IDENTIFIER : syncfilerange01 * * EXECUTED BY : anyone * * TEST TITLE : Checks for Errors from sync_file_range() * * TEST CASE TOTAL : 5 * * CPU ARCHITECTURES : All * * AUTHOR : B N Poornima * * DATE STARTED : 21/07/2008 * * TEST CASES * (Tests sync_file_range() for different test cases as reported in the man * page) * * INPUT SPECIFICATIONS * No input needs to be specified * sync_file_data() in-puts are specified through test_data * * OUTPUT SPECIFICATIONS * sync_file_data() error message matches with the expected error * message. * * * ENVIRONMENTAL NEEDS * None * * SPECIAL PROCEDURAL REQUIREMENTS * None * * DETAILED DESCRIPTION * This is a test case for sync_file_range() system call. * This test suite tests various error messages from the system call * If the error message received matches with the expected * test is considered passed else test fails * * Total 5 Test Cases :- * Various error messages from the man page * * Setup: * Setup files on which sync_file_range is to be called * * Test: * Loop if the proper options are given. * Execute system call * Check return code. * If error obtained matches with the expected error * PASS the test, otherwise TEST FAILS * * Cleanup: * Cleanup the temporary folder * ******************************************************************************/ #define _GNU_SOURCE /* Standard Include Files */ #include <stdio.h> #include <stdlib.h> #include <errno.h> #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h> #include <sys/utsname.h> #include <unistd.h> /* Harness Specific Include Files. */ #include "test.h" #include "usctest.h" #include "linux_syscall_numbers.h" #ifndef __NR_sync_file_range #define __NR_sync_file_range -1 //DUMMY VALUE int arch_support = 0; //Architecure is not supported #else int arch_support = 1; //Architecture is supported #endif #ifdef __powerpc64__ # ifndef __NR_sync_file_range2 # define __NR_sync_file_range2 308 #endif #endif #ifndef SYNC_FILE_RANGE_WAIT_BEFORE #define SYNC_FILE_RANGE_WAIT_BEFORE 1 #define SYNC_FILE_RANGE_WRITE 2 //DUMMY VALUES #define SYNC_FILE_RANGE_WAIT_AFTER 4 #endif #define SYNC_FILE_RANGE_INVALID 8 /* Extern Global Variables */ extern int Tst_count; /* counter for tst_xxx routines. */ extern char *TESTDIR; /* temporary dir created by tst_tmpdir() */ /* Global Variables */ char *TCID = "syncfilerange01"; /* test program identifier. */ char filename[255]; /* file used for testing */ char spl_file[] = "/dev/null"; int filed, sfd; /* normal and special fds */ int bfd = -1; /* Bad file descriptor */ struct test_data_t { int *fd; off64_t offset; off64_t nbytes; unsigned int flags; int error; } test_data[] = { {&bfd, 0, 1, SYNC_FILE_RANGE_WRITE, EBADF}, {&sfd, 0, 1, SYNC_FILE_RANGE_WAIT_AFTER, ESPIPE}, {&filed, -1, 1, SYNC_FILE_RANGE_WAIT_BEFORE, EINVAL}, {&filed, 0, -1, SYNC_FILE_RANGE_WRITE, EINVAL}, {&filed, 0, 1, SYNC_FILE_RANGE_INVALID, EINVAL} }; int TST_TOTAL = sizeof(test_data) / sizeof(test_data[0]); /* Extern Global Functions */ /******************************************************************************/ /* */ /* Function: cleanup */ /* */ /* Description: Performs all one time clean up for this test on successful */ /* completion, premature exit or failure. Closes all temporary */ /* files, removes all temporary directories exits the test with */ /* appropriate return code by calling tst_exit() function. */ /* */ /* Input: None. */ /* */ /* Output: None. */ /* */ /* Return: On failure - Exits calling tst_exit(). Non '0' return code. */ /* On success - Exits calling tst_exit(). With '0' return code. */ /* */ /******************************************************************************/ extern void cleanup() { /* * print timing stats if that option was specified. * print errno log if that option was specified. */ TEST_CLEANUP; /* close the file we have open */ if (close(filed) == -1) { tst_resm(TWARN, "close(%s) Failed, errno=%d : %s", filename, errno, strerror(errno)); } /* Remove tmp dir and all files in it */ tst_rmdir(); /* exit with return code appropriate for results */ tst_exit(); tst_exit(); } /* Local Functions */ /******************************************************************************/ /* */ /* Function: setup */ /* */ /* Description: Performs all one time setup for this test. This function is */ /* typically used to capture signals, create temporary dirs */ /* and temporary files that may be used in the course of this */ /* test. */ /* */ /* Input: None. */ /* */ /* */ /* Output: None. */ /* */ /* Return: On failure - Exits by calling cleanup(). */ /* On success - returns 0. */ /* */ /******************************************************************************/ void setup() { /* capture signals */ tst_sig(NOFORK, DEF_HANDLER, cleanup); /* Pause if that option was specified */ TEST_PAUSE; /* make a temp directory and cd to it */ tst_tmpdir(); sprintf(filename,"tmpfile_%d",getpid()); if ((filed = open(filename,O_RDWR|O_CREAT,0700)) == -1) { tst_brkm(TBROK, cleanup, "open(%s, O_RDWR|O_CREAT,0700) Failed, errno=%d : %s", filename, errno, strerror(errno)); sfd = open(spl_file, O_RDWR|O_CREAT, 0700); } return; } /***************************************************************************** * Wraper function to call sync_file_range system call ******************************************************************************/ static inline long syncfilerange(int fd, off64_t offset, off64_t nbytes, unsigned int flags) { #if defined(__powerpc64__) && (__WORDSIZE==32) return syscall(__NR_sync_file_range2, fd, flags, (int)(offset >>32), \ (int)offset, (int)(nbytes >>32), (int)nbytes); #elif defined(__powerpc64__) && (__WORDSIZE==64) return syscall(__NR_sync_file_range2, fd, flags, offset, nbytes); #endif return syscall(__NR_sync_file_range, fd, offset, nbytes, flags); return 0; } /******************************************************************************/ /* */ /* Function: main */ /* */ /* Description: Entry point to this test-case. It parses all the command line */ /* inputs, calls the global setup and executes the test. It logs */ /* the test status and results appropriately using the LTP API's */ /* On successful completion or premature failure, cleanup() func */ /* is called and test exits with an appropriate return code. */ /* */ /* Input: Describe input arguments to this test-case */ /* -l - Number of iteration */ /* -v - Prints verbose output */ /* -V - Prints the version number */ /* */ /* Exit: On failure - Exits by calling cleanup(). */ /* On success - exits with 0 exit value. */ /* */ /******************************************************************************/ int main(int ac, /* number of command line parameters */ char **av) /* pointer to the array of the command line parameters. */ { int test_index = 0; int lc; char *msg; /*************************************************************** parse standard options ********************************************************************/ if ( (msg=parse_opts(ac, av, (option_t *) NULL, NULL)) != (char *) NULL ) tst_brkm(TBROK, cleanup, "OPTION PARSING ERROR - %s", msg); /* This test needs kernel version > 2.6.16 */ if ( !arch_support || (tst_kvercmp(2,6,17) < 0)) { tst_resm(TWARN," System doesn't support execution of the test"); exit(0); } /* perform global test setup, call setup() function. */ setup(); for (lc=0; TEST_LOOPING(lc); lc++) { /* reset Tst_count in case we are looping. */ Tst_count=0; for(test_index = 0 ; test_index < TST_TOTAL; test_index ++) { TEST(syncfilerange(*(test_data[test_index].fd), test_data[test_index].offset, \ test_data[test_index].nbytes, test_data[test_index].flags)); if (TEST_RETURN != -1) { tst_resm(TFAIL, "call succeeded unexpectedly"); continue; } TEST_ERROR_LOG(TEST_ERRNO); if (TEST_ERRNO == test_data[test_index].error) { tst_resm(TPASS, "expected failure - " "errno = %d : %s", TEST_ERRNO, strerror(TEST_ERRNO)); } else { tst_resm(TFAIL, "unexpected error - %d : %s - " "expected %d", TEST_ERRNO, strerror(TEST_ERRNO), test_data[test_index].error); } } } cleanup(); return(0); } |