Improved tests for utime() and utimes(). Close #4399 --- testsuites/psxtests/psx13/main.c | 2 - testsuites/psxtests/psx13/test.c | 484 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 471 insertions(+), 15 deletions(-)
diff --git a/testsuites/psxtests/psx13/main.c b/testsuites/psxtests/psx13/main.c index f9e7907..44267bd 100644 --- a/testsuites/psxtests/psx13/main.c +++ b/testsuites/psxtests/psx13/main.c @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - /** * @file * diff --git a/testsuites/psxtests/psx13/test.c b/testsuites/psxtests/psx13/test.c index e98b03a..bb7a201 100644 --- a/testsuites/psxtests/psx13/test.c +++ b/testsuites/psxtests/psx13/test.c @@ -1,5 +1,3 @@ -/* SPDX-License-Identifier: BSD-2-Clause */ - /** * @file * @@ -17,6 +15,8 @@ * - umask() * - utime() * - utimes() + * - utimensat() + * - futimens() * - sync() */ @@ -210,8 +210,7 @@ static void Dup2Test( void ) } /** - * @brief Exercises fdatasync(). Does NOT test the functionality of the - * underlying fdatasync entry in the IMFS op table. + * @brief Exercises fdatasync(). */ static void FDataSyncTest( void ) { @@ -259,13 +258,13 @@ static void UMaskTest( void ) } /** - * @brief Exercises utime(). Does not test the functionality of the - * underlying utime entry in the IMFS op table. + * @brief Exercises utime(). */ static void UTimeTest( void ) { int rv; struct utimbuf time; + struct timespec current_time; struct stat fstat; /* First, an invalid filename. */ @@ -273,6 +272,57 @@ static void UTimeTest( void ) rtems_test_assert( rv == -1 ); rtems_test_assert( errno == ENOENT ); + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + + /* Change the owner of the file temporarily */ + rv = chown( "testfile1.tst", 123, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + rv = utime( "testfile1.tst", &time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chown( "testfile1.tst", fstat.st_uid, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + /* Change file to be read-only */ + rv = chmod( "testfile1.tst", 06444 ); + rtems_test_assert( rv == 0 ); + + rv = utime( "testfile1.tst", &time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chmod( "testfile1.tst", fstat.st_mode ); + rtems_test_assert( rv == 0 ); + + /* Test without times argument */ + clock_gettime( CLOCK_REALTIME, ¤t_time ); + + rv = utime( "testfile1.tst", NULL ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec ); + rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec ); + + /* Pass invalid values */ + time.actime = -1; + time.modtime = 54321; + + rv = utime( "testfile1.tst", &time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time.actime = 12345; + time.modtime = -1; + + rv = utime( "testfile1.tst", &time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + /* Now, the success test. */ time.actime = 12345; time.modtime = 54321; @@ -280,24 +330,22 @@ static void UTimeTest( void ) rv = utime( "testfile1.tst", &time ); rtems_test_assert( rv == 0 ); - /* But, did it set the time? */ + /* Check that it actually changed the time */ rv = stat( "testfile1.tst", &fstat ); rtems_test_assert( rv == 0 ); rtems_test_assert( fstat.st_atime == 12345 ); rtems_test_assert( fstat.st_mtime == 54321 ); - rv = utime( "testfile1.tst", NULL ); - rtems_test_assert( rv == 0 ); } /** - * @brief Exercises utimes(). Does NOT test the functionality of the - * underlying utime entry in the IMFS op table. + * @brief Exercises utimes(). */ static void UTimesTest( void ) { int rv; struct timeval time[2]; + struct timespec current_time; struct stat fstat; /* First, an invalid filename. */ @@ -305,14 +353,422 @@ static void UTimesTest( void ) rtems_test_assert( rv == -1 ); rtems_test_assert( errno == ENOENT ); + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + + /* Change the owner of the file temporarily */ + rv = chown( "testfile1.tst", 123, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chown( "testfile1.tst", fstat.st_uid, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + /* Change file to be read-only */ + rv = chmod( "testfile1.tst", 06444 ); + rtems_test_assert( rv == 0 ); + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chmod( "testfile1.tst", fstat.st_mode ); + rtems_test_assert( rv == 0 ); + + /* Test without times argument */ + clock_gettime( CLOCK_REALTIME, ¤t_time ); + + rv = utimes( "testfile1.tst", NULL ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec ); + rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec ); + + /* Pass invalid values */ + + /* Negative second tests */ + time[0].tv_sec = -1; + time[0].tv_usec = 12345; + time[1].tv_sec = 54321; + time[1].tv_usec = 54321; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[0].tv_sec = 12345; + time[1].tv_sec = -1; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Negative microsecond tests */ + time[1].tv_sec = 54321; + time[0].tv_usec = -1; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[0].tv_usec = 12345; + time[1].tv_usec = -1; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Testing max range */ + time[0].tv_usec = 1000000000; + time[1].tv_usec = 54321; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[1].tv_usec = 1000000000; + time[0].tv_usec = 12345; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + /* Now, the success test. */ time[0].tv_sec = 12345; + time[0].tv_usec = 12345; + time[1].tv_sec = 54321; + time[1].tv_usec = 54321; + + rv = utimes( "testfile1.tst", time ); + rtems_test_assert( rv == 0 ); + + /* Check that it actually changed the time */ + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( fstat.st_atime == 12345 ); + rtems_test_assert( fstat.st_mtime == 54321 ); +} + +/** + * @brief Exercises utimensat(). + */ +static void UTimensatTest( void ) +{ + int rv; + struct timespec time[2]; + struct timespec current_time; + struct stat fstat; + + /* Pass an unsupported file descriptor */ + rv = utimensat( + 0, + "!This is an =invalid p@thname!!! : )", + NULL, + 0 + ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == ENOSYS ); + + /* Pass unsupported flag */ + rv = utimensat( + AT_FDCWD, + "!This is an =invalid p@thname!!! : )", + NULL, + 1 + ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == ENOSYS ); + + /* Use an invalid filename. */ + rv = utimensat( + AT_FDCWD, + "!This is an =invalid p@thname!!! : )", + NULL, + 0 + ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == ENOENT ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + + /* Change the owner of the file temporarily */ + rv = chown( "testfile1.tst", 123, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chown( "testfile1.tst", fstat.st_uid, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + /* Change file to be read-only */ + rv = chmod( "testfile1.tst", 06444 ); + rtems_test_assert( rv == 0 ); + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chmod( "testfile1.tst", fstat.st_mode ); + rtems_test_assert( rv == 0 ); + + /* Test without times argument */ + clock_gettime( CLOCK_REALTIME, ¤t_time ); + + rv = utimensat( AT_FDCWD, "testfile1.tst", NULL, 0 ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec ); + rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec ); + + /* Pass invalid values */ + + /* Negative second tests */ + time[0].tv_sec = -12345; + time[0].tv_nsec = 12345; + time[1].tv_sec = 54321; + time[1].tv_nsec = 54321; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[0].tv_sec = 12345; + time[1].tv_sec = -54321; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Negative microsecond tests */ + time[1].tv_sec = 54321; + time[0].tv_nsec = -12345; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[0].tv_nsec = 12345; + time[1].tv_nsec = -54321; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Testing max range */ + time[0].tv_nsec = 1000000000; + time[1].tv_nsec = 54321; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[1].tv_nsec = 1000000000; + time[0].tv_nsec = 12345; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Now, the successful test cases. */ + + /* Running with access time nanosecond field equal to UTIME_NOW */ + time[0].tv_sec = 12345; + time[0].tv_nsec = UTIME_NOW; + time[1].tv_sec = 54321; + time[1].tv_nsec = 54321; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec ); + rtems_test_assert( fstat.st_mtime == 54321 ); + + /* Running with modified time nanosecond field equal to UTIME_NOW */ + time[0].tv_sec = 12345; + time[0].tv_nsec = 12345; + time[1].tv_sec = 54321; + time[1].tv_nsec = UTIME_NOW; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( fstat.st_atime == 12345 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec ); + + /* Normal run */ + time[0].tv_sec = 12345; + time[0].tv_nsec = 12345; + time[1].tv_sec = 54321; + time[1].tv_nsec = 54321; + + rv = utimensat( AT_FDCWD, "testfile1.tst", time, 0 ); + rtems_test_assert( rv == 0 ); + + /* Check that it actually changed the time */ + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( fstat.st_atime == 12345 ); + rtems_test_assert( fstat.st_mtime == 54321 ); +} + +/** + * @brief Exercises futimens(). + */ +static void FutimensTest( void ) +{ + int rv; + int fd; + struct timespec time[2]; + struct timespec current_time; + struct stat fstat; + + /* Pass an invalid file descriptor */ + rv = futimens( -1, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EBADF ); + + fd = open( "testfile1.tst", O_RDWR ); + rtems_test_assert( fd != -1 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + + /* Change the owner of the file temporarily */ + rv = chown( "testfile1.tst", 123, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chown( "testfile1.tst", fstat.st_uid, fstat.st_gid ); + rtems_test_assert( rv == 0 ); + + /* Change file to be read-only */ + rv = chmod( "testfile1.tst", 06444 ); + rtems_test_assert( rv == 0 ); + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EACCES ); + + rv = chmod( "testfile1.tst", fstat.st_mode ); + rtems_test_assert( rv == 0 ); + + /* Test without times argument */ + clock_gettime( CLOCK_REALTIME, ¤t_time ); + + rv = futimens( fd, NULL ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec ); + rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec ); + + /* Pass invalid values */ + + /* Negative second tests */ + time[0].tv_sec = -12345; + time[0].tv_nsec = 12345; + time[1].tv_sec = 54321; + time[1].tv_nsec = 54321; + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[0].tv_sec = 12345; + time[1].tv_sec = -54321; + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Negative microsecond tests */ + time[1].tv_sec = 54321; + time[0].tv_nsec = -12345; + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[0].tv_nsec = 12345; + time[1].tv_nsec = -54321; + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Testing max range */ + time[0].tv_nsec = 1000000000; + time[1].tv_nsec = 54321; + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + time[1].tv_nsec = 1000000000; + time[0].tv_nsec = 12345; + + rv = futimens( fd, time ); + rtems_test_assert( rv == -1 ); + rtems_test_assert( errno == EINVAL ); + + /* Now, the successful test cases. */ + + /* Running with access time nanosecond field equal to UTIME_NOW */ + time[0].tv_sec = 12345; + time[0].tv_nsec = UTIME_NOW; + time[1].tv_sec = 54321; + time[1].tv_nsec = 54321; + + rv = futimens( fd, time ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_atim.tv_sec ); + rtems_test_assert( fstat.st_mtime == 54321 ); + + /* Running with modified time nanosecond field equal to UTIME_NOW */ + time[0].tv_sec = 12345; + time[0].tv_nsec = 12345; + time[1].tv_sec = 54321; + time[1].tv_nsec = UTIME_NOW; + + rv = futimens( fd, time ); + rtems_test_assert( rv == 0 ); + + rv = stat( "testfile1.tst", &fstat ); + rtems_test_assert( rv == 0 ); + rtems_test_assert( fstat.st_atime == 12345 ); + rtems_test_assert( current_time.tv_sec <= fstat.st_mtim.tv_sec ); + + /* Normal run */ + time[0].tv_sec = 12345; + time[0].tv_nsec = 12345; time[1].tv_sec = 54321; + time[1].tv_nsec = 54321; - rv = utimes( "testfile1.tst", (struct timeval *)&time ); + rv = futimens( fd, time ); rtems_test_assert( rv == 0 ); - /* But, did it set the time? */ + /* Check that it actually changed the time */ rv = stat( "testfile1.tst", &fstat ); rtems_test_assert( rv == 0 ); rtems_test_assert( fstat.st_atime == 12345 ); @@ -443,6 +899,8 @@ int test_main( void ) UMaskTest(); UTimeTest(); UTimesTest(); + UTimensatTest(); + FutimensTest(); FSyncTest(); PathConfTest(); FPathConfTest(); -- 1.8.3.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel