1//===-- Unittests for utimes ----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "hdr/fcntl_macros.h"
10#include "hdr/sys_stat_macros.h"
11#include "hdr/types/struct_timeval.h"
12#include "src/fcntl/open.h"
13#include "src/stdio/remove.h"
14#include "src/sys/stat/stat.h"
15#include "src/sys/time/utimes.h"
16#include "src/unistd/close.h"
17
18#include "test/UnitTest/ErrnoCheckingTest.h"
19#include "test/UnitTest/ErrnoSetterMatcher.h"
20#include "test/UnitTest/Test.h"
21
22using LlvmLibcUtimesTest = LIBC_NAMESPACE::testing::ErrnoCheckingTest;
23
24// SUCCESS: Takes a file and successfully updates
25// its last access and modified times.
26TEST_F(LlvmLibcUtimesTest, ChangeTimesSpecific) {
27 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
28
29 constexpr const char *FILE_PATH = "utimes_pass.test";
30 auto TEST_FILE = libc_make_test_file_path(FILE_PATH);
31 int fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
32 ASSERT_ERRNO_SUCCESS();
33 ASSERT_GT(fd, 0);
34 ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
35
36 // make a dummy timeval struct
37 struct timeval times[2];
38 times[0].tv_sec = 54321;
39 times[0].tv_usec = 12345;
40 times[1].tv_sec = 43210;
41 times[1].tv_usec = 23456;
42
43 // ensure utimes succeeds
44 ASSERT_THAT(LIBC_NAMESPACE::utimes(TEST_FILE, times), Succeeds(0));
45
46 // verify the times values against stat of the TEST_FILE
47 struct stat statbuf;
48 ASSERT_EQ(LIBC_NAMESPACE::stat(TEST_FILE, &statbuf), 0);
49
50 // seconds
51 ASSERT_EQ(statbuf.st_atim.tv_sec, times[0].tv_sec);
52 ASSERT_EQ(statbuf.st_mtim.tv_sec, times[1].tv_sec);
53
54 // microseconds
55 ASSERT_EQ(statbuf.st_atim.tv_nsec,
56 static_cast<long>(times[0].tv_usec * 1000));
57 ASSERT_EQ(statbuf.st_mtim.tv_nsec,
58 static_cast<long>(times[1].tv_usec * 1000));
59
60 ASSERT_THAT(LIBC_NAMESPACE::remove(TEST_FILE), Succeeds(0));
61}
62
63// FAILURE: Invalid values in the timeval struct
64// to check that utimes rejects it.
65TEST_F(LlvmLibcUtimesTest, InvalidMicroseconds) {
66 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Fails;
67 using LIBC_NAMESPACE::testing::ErrnoSetterMatcher::Succeeds;
68
69 constexpr const char *FILE_PATH = "utimes_fail.test";
70 auto TEST_FILE = libc_make_test_file_path(FILE_PATH);
71 int fd = LIBC_NAMESPACE::open(TEST_FILE, O_WRONLY | O_CREAT, S_IRWXU);
72 ASSERT_GT(fd, 0);
73 ASSERT_THAT(LIBC_NAMESPACE::close(fd), Succeeds(0));
74
75 // make a dummy timeval struct
76 // populated with bad usec values
77 struct timeval times[2];
78 times[0].tv_sec = 54321;
79 times[0].tv_usec = 4567;
80 times[1].tv_sec = 43210;
81 times[1].tv_usec = 1000000; // invalid
82
83 // ensure utimes fails
84 ASSERT_THAT(LIBC_NAMESPACE::utimes(TEST_FILE, times), Fails(EINVAL));
85
86 // check for failure on
87 // the other possible bad values
88
89 times[0].tv_sec = 54321;
90 times[0].tv_usec = -4567; // invalid
91 times[1].tv_sec = 43210;
92 times[1].tv_usec = 1000;
93
94 // ensure utimes fails once more
95 ASSERT_THAT(LIBC_NAMESPACE::utimes(TEST_FILE, times), Fails(EINVAL));
96 ASSERT_THAT(LIBC_NAMESPACE::remove(TEST_FILE), Succeeds(0));
97}
98

source code of libc/test/src/sys/time/utimes_test.cpp