test_file_io.c
上传用户:shw771010
上传日期:2022-01-05
资源大小:991k
文件大小:14k
- /*
- ** Copyright (C) 2002-2009 Erik de Castro Lopo <erikd@mega-nerd.com>
- **
- ** This program is free software; you can redistribute it and/or modify
- ** it under the terms of the GNU Lesser General Public License as published by
- ** the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
- **
- ** You should have received a copy of the GNU Lesser 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.
- */
- #include "sfconfig.h"
- #include <stdio.h>
- #include <stdlib.h>
- #if HAVE_UNISTD_H
- #include <unistd.h>
- #endif
- #include <string.h>
- #include <errno.h>
- #include <inttypes.h>
- #include "common.h"
- #include "test_main.h"
- static void make_data (int *data, int len, int seed) ;
- static void file_open_test (const char *filename) ;
- static void file_read_write_test (const char *filename) ;
- static void file_truncate_test (const char *filename) ;
- static void test_open_or_die (SF_PRIVATE *psf, int linenum) ;
- static void test_close_or_die (SF_PRIVATE *psf, int linenum) ;
- static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
- static void test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
- static void test_equal_or_die (int *array1, int *array2, int len, int linenum) ;
- static void test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) ;
- /*==============================================================================
- ** Actual test functions.
- */
- static void
- file_open_test (const char *filename)
- { SF_PRIVATE sf_data, *psf ;
- int error ;
- print_test_name ("Testing file open") ;
- memset (&sf_data, 0, sizeof (sf_data)) ;
- psf = &sf_data ;
- /* Ensure that the file doesn't already exist. */
- if (unlink (filename) != 0 && errno != ENOENT)
- { printf ("nnLine %d: unlink failed (%d) : %snn", __LINE__, errno, strerror (errno)) ;
- exit (1) ;
- } ;
- psf->file.mode = SFM_READ ;
- snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
- /* Test that open for read fails if the file doesn't exist. */
- error = psf_fopen (psf) ;
- if (error == 0)
- { printf ("nnLine %d: psf_fopen() should have failed.nn", __LINE__) ;
- exit (1) ;
- } ;
- /* Reset error to zero. */
- psf->error = SFE_NO_ERROR ;
- /* Test file open in write mode. */
- psf->file.mode = SFM_WRITE ;
- test_open_or_die (psf, __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- unlink (psf->file.path.c) ;
- /* Test file open in read/write mode for a non-existant file. */
- psf->file.mode = SFM_RDWR ;
- test_open_or_die (psf, __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- /* Test file open in read/write mode for an existing file. */
- psf->file.mode = SFM_RDWR ;
- test_open_or_die (psf, __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- unlink (psf->file.path.c) ;
- puts ("ok") ;
- } /* file_open_test */
- static void
- file_read_write_test (const char *filename)
- { static int data_out [512] ;
- static int data_in [512] ;
- SF_PRIVATE sf_data, *psf ;
- sf_count_t retval ;
- /*
- ** Open a new file and write two blocks of data to the file. After each
- ** write, test that psf_get_filelen() returns the new length.
- */
- print_test_name ("Testing file write") ;
- memset (&sf_data, 0, sizeof (sf_data)) ;
- psf = &sf_data ;
- snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
- /* Test file open in write mode. */
- psf->file.mode = SFM_WRITE ;
- test_open_or_die (psf, __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 1) ;
- test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), sizeof (data_out), __LINE__) ;
- if ((retval = psf_get_filelen (psf)) != sizeof (data_out))
- { printf ("nnLine %d: file length after write is not correct (%" PRId64 " should be %zd).nn", __LINE__, retval, sizeof (data_out)) ;
- if (retval == 0)
- printf ("An fsync() may be necessary before fstat() in psf_get_filelen().nn") ;
- exit (1) ;
- } ;
- make_data (data_out, ARRAY_LEN (data_out), 2) ;
- test_write_or_die (psf, data_out, ARRAY_LEN (data_out), sizeof (data_out [0]), 2 * sizeof (data_out), __LINE__) ;
- if ((retval = psf_get_filelen (psf)) != 2 * sizeof (data_out))
- { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %zd)nn", __LINE__, retval, 2 * sizeof (data_out)) ;
- exit (1) ;
- } ;
- test_close_or_die (psf, __LINE__) ;
- puts ("ok") ;
- /*
- ** Now open the file in read mode, check the file length and check
- ** that the data is correct.
- */
- print_test_name ("Testing file read") ;
- /* Test file open in write mode. */
- psf->file.mode = SFM_READ ;
- test_open_or_die (psf, __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 1) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 2) ;
- test_read_or_die (psf, data_in, sizeof (data_in [0]), ARRAY_LEN (data_in), 2 * sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- puts ("ok") ;
- /*
- ** Open the file in read/write mode, seek around a bit and then seek to
- ** the end of the file and write another block of data (3rd block). Then
- ** go back and check that all three blocks are correct.
- */
- print_test_name ("Testing file seek") ;
- /* Test file open in read/write mode. */
- psf->file.mode = SFM_RDWR ;
- test_open_or_die (psf, __LINE__) ;
- test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
- test_seek_or_die (psf, 0, SEEK_END, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
- test_seek_or_die (psf, -1 * SIGNED_SIZEOF (data_out), SEEK_CUR, (sf_count_t) sizeof (data_out), __LINE__) ;
- test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_CUR, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 3) ;
- test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 3 * sizeof (data_out), __LINE__) ;
- test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 1) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- test_seek_or_die (psf, 2 * SIGNED_SIZEOF (data_out), SEEK_SET, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 3) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 2) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- puts ("ok") ;
- /*
- ** Now test operations with a non-zero psf->fileoffset field. This field
- ** sets an artificial file start positions so that a seek to the start of
- ** the file will actually be a seek to the value given by psf->fileoffset.
- */
- print_test_name ("Testing file offset") ;
- /* Test file open in read/write mode. */
- psf->file.mode = SFM_RDWR ;
- psf->fileoffset = sizeof (data_out [0]) * ARRAY_LEN (data_out) ;
- test_open_or_die (psf, __LINE__) ;
- if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
- { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %zd)nn", __LINE__, retval, 3 * sizeof (data_out)) ;
- exit (1) ;
- } ;
- test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 5) ;
- test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 2 * sizeof (data_out), __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- /* final test with psf->fileoffset == 0. */
- psf->file.mode = SFM_RDWR ;
- psf->fileoffset = 0 ;
- test_open_or_die (psf, __LINE__) ;
- if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
- { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %zd)nn", __LINE__, retval, 3 * sizeof (data_out)) ;
- exit (1) ;
- } ;
- make_data (data_out, ARRAY_LEN (data_out), 1) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 2) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- make_data (data_out, ARRAY_LEN (data_out), 5) ;
- test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
- test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- puts ("ok") ;
- } /* file_read_write_test */
- static void
- file_truncate_test (const char *filename)
- { SF_PRIVATE sf_data, *psf ;
- unsigned char buffer [256] ;
- int k ;
- /*
- ** Open a new file and write two blocks of data to the file. After each
- ** write, test that psf_get_filelen() returns the new length.
- */
- print_test_name ("Testing file truncate") ;
- memset (&sf_data, 0, sizeof (sf_data)) ;
- memset (buffer, 0xEE, sizeof (buffer)) ;
- psf = &sf_data ;
- snprintf (psf->file.path.c, sizeof (psf->file.path.c), "%s", filename) ;
- /*
- ** Open the file write mode, write 0xEE data and then extend the file
- ** using truncate (the extended data should be 0x00).
- */
- psf->file.mode = SFM_WRITE ;
- test_open_or_die (psf, __LINE__) ;
- test_write_or_die (psf, buffer, sizeof (buffer) / 2, 1, sizeof (buffer) / 2, __LINE__) ;
- psf_ftruncate (psf, sizeof (buffer)) ;
- test_close_or_die (psf, __LINE__) ;
- /* Open the file in read mode and check the data. */
- psf->file.mode = SFM_READ ;
- test_open_or_die (psf, __LINE__) ;
- test_read_or_die (psf, buffer, sizeof (buffer), 1, sizeof (buffer), __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++)
- if (buffer [k] != 0xEE)
- { printf ("nnLine %d : buffer [%d] = %d (should be 0xEE)nn", __LINE__, k, buffer [k]) ;
- exit (1) ;
- } ;
- for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++)
- if (buffer [k] != 0)
- { printf ("nnLine %d : buffer [%d] = %d (should be 0)nn", __LINE__, k, buffer [k]) ;
- exit (1) ;
- } ;
- /* Open the file in read/write and shorten the file using truncate. */
- psf->file.mode = SFM_RDWR ;
- test_open_or_die (psf, __LINE__) ;
- psf_ftruncate (psf, sizeof (buffer) / 4) ;
- test_close_or_die (psf, __LINE__) ;
- /* Check the file length. */
- psf->file.mode = SFM_READ ;
- test_open_or_die (psf, __LINE__) ;
- test_seek_or_die (psf, 0, SEEK_END, SIGNED_SIZEOF (buffer) / 4, __LINE__) ;
- test_close_or_die (psf, __LINE__) ;
- puts ("ok") ;
- } /* file_truncate_test */
- /*==============================================================================
- ** Testing helper functions.
- */
- static void
- test_open_or_die (SF_PRIVATE *psf, int linenum)
- { int error ;
- /* Test that open for read fails if the file doesn't exist. */
- error = psf_fopen (psf) ;
- if (error)
- { printf ("nnLine %d: psf_fopen() failed : %snn", linenum, strerror (errno)) ;
- exit (1) ;
- } ;
- } /* test_open_or_die */
- static void
- test_close_or_die (SF_PRIVATE *psf, int linenum)
- {
- psf_fclose (psf) ;
- if (psf_file_valid (psf))
- { printf ("nnLine %d: psf->file.filedes should not be valid.nn", linenum) ;
- exit (1) ;
- } ;
- } /* test_close_or_die */
- static void
- test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
- { sf_count_t retval ;
- retval = psf_fwrite (data, bytes, items, psf) ;
- if (retval != items)
- { printf ("nnLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")nn", linenum, retval, items) ;
- exit (1) ;
- } ;
- if ((retval = psf_ftell (psf)) != new_position)
- { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")nn", linenum, retval, new_position) ;
- exit (1) ;
- } ;
- return ;
- } /* test_write_or_die */
- static void
- test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
- { sf_count_t retval ;
- retval = psf_fread (data, bytes, items, psf) ;
- if (retval != items)
- { printf ("nnLine %d: psf_write() returned %" PRId64 " (should be %" PRId64 ")nn", linenum, retval, items) ;
- exit (1) ;
- } ;
- if ((retval = psf_ftell (psf)) != new_position)
- { printf ("nnLine %d: file length after write is not correct. (%" PRId64 " should be %" PRId64 ")nn", linenum, retval, new_position) ;
- exit (1) ;
- } ;
- return ;
- } /* test_write_or_die */
- static void
- test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum)
- { sf_count_t retval ;
- retval = psf_fseek (psf, offset, whence) ;
- if (retval != new_position)
- { printf ("nnLine %d: psf_fseek() failed. New position is %" PRId64 " (should be %" PRId64 ").nn",
- linenum, retval, new_position) ;
- exit (1) ;
- } ;
- } /* test_seek_or_die */
- static void
- test_equal_or_die (int *array1, int *array2, int len, int linenum)
- { int k ;
- for (k = 0 ; k < len ; k++)
- if (array1 [k] != array2 [k])
- printf ("nnLine %d: error at index %d (%d != %d).nn",
- linenum, k, array1 [k], array2 [k]) ;
- return ;
- } /* test_equal_or_die */
- static void
- make_data (int *data, int len, int seed)
- { int k ;
- srand (seed * 3333333 + 14756123) ;
- for (k = 0 ; k < len ; k++)
- data [k] = rand () ;
- } /* make_data */
- void
- test_file_io (void)
- { const char *filename = "file_io.dat" ;
- file_open_test (filename) ;
- file_read_write_test (filename) ;
- file_truncate_test (filename) ;
- unlink (filename) ;
- } /* main */