xref: /llvm-project/flang/unittests/Runtime/AccessTest.cpp (revision 32403f79f4fcdb74b1576eed19cde7b104191808)
1668a58b8STom Eccles //===-- flang/unittests/Runtime/AccessTest.cpp ----------------------------===//
2668a58b8STom Eccles //
3668a58b8STom Eccles // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4668a58b8STom Eccles // See https://llvm.org/LICENSE.txt for license information.
5668a58b8STom Eccles // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6668a58b8STom Eccles //
7668a58b8STom Eccles //===----------------------------------------------------------------------===//
8668a58b8STom Eccles 
9668a58b8STom Eccles // TODO: ACCESS is not yet implemented on Windows
10668a58b8STom Eccles #ifndef _WIN32
11668a58b8STom Eccles 
12668a58b8STom Eccles #include "CrashHandlerFixture.h"
13668a58b8STom Eccles #include "gtest/gtest.h"
14668a58b8STom Eccles #include "flang/Runtime/extensions.h"
15668a58b8STom Eccles #include "llvm/ADT/Twine.h"
16668a58b8STom Eccles 
17668a58b8STom Eccles #include <fcntl.h>
18668a58b8STom Eccles #include <sys/stat.h>
19668a58b8STom Eccles #include <sys/types.h>
20668a58b8STom Eccles #include <unistd.h>
21668a58b8STom Eccles 
22668a58b8STom Eccles namespace {
23668a58b8STom Eccles 
24668a58b8STom Eccles struct AccessTests : public CrashHandlerFixture {};
25668a58b8STom Eccles 
26668a58b8STom Eccles struct AccessType {
27668a58b8STom Eccles   bool read{false};
28668a58b8STom Eccles   bool write{false};
29668a58b8STom Eccles   bool execute{false};
30668a58b8STom Eccles   bool exists{false};
31668a58b8STom Eccles };
32668a58b8STom Eccles 
33668a58b8STom Eccles } // namespace
34668a58b8STom Eccles 
35*32403f79STom Eccles static bool userSkipsPermissionChecks() {
36*32403f79STom Eccles   // The tests in this file assume normal permission checks apply to the user
37*32403f79STom Eccles   // running the tests. This isn't true when the test is run by root.
38*32403f79STom Eccles   return geteuid() == 0;
39*32403f79STom Eccles }
40*32403f79STom Eccles 
41668a58b8STom Eccles static std::string addPIDSuffix(const char *name) {
42668a58b8STom Eccles   std::stringstream ss;
43668a58b8STom Eccles   ss << name;
44668a58b8STom Eccles   ss << '.';
45668a58b8STom Eccles 
46668a58b8STom Eccles   ss << getpid();
47668a58b8STom Eccles 
48668a58b8STom Eccles   return ss.str();
49668a58b8STom Eccles }
50668a58b8STom Eccles 
51668a58b8STom Eccles static bool exists(const std::string &path) {
52668a58b8STom Eccles   return access(path.c_str(), F_OK) == 0;
53668a58b8STom Eccles }
54668a58b8STom Eccles 
55668a58b8STom Eccles // Implementation of std::filesystem::temp_directory_path adapted from libcxx
56668a58b8STom Eccles // See llvm-project/libcxx/src/filesystem/operations.cpp
57668a58b8STom Eccles // Using std::filesystem is inconvenient because the required flags are not
58668a58b8STom Eccles // consistent accross compilers and CMake doesn't have built in support to
59668a58b8STom Eccles // determine the correct flags.
60668a58b8STom Eccles static const char *temp_directory_path() {
61668a58b8STom Eccles   // TODO: Windows
62668a58b8STom Eccles   const char *env_paths[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR"};
63668a58b8STom Eccles   const char *ret = nullptr;
64668a58b8STom Eccles 
65668a58b8STom Eccles   for (auto &ep : env_paths) {
66668a58b8STom Eccles     if ((ret = getenv(ep))) {
67668a58b8STom Eccles       break;
68668a58b8STom Eccles     }
69668a58b8STom Eccles   }
70668a58b8STom Eccles 
71668a58b8STom Eccles   if (ret == nullptr) {
72668a58b8STom Eccles #if defined(__ANDROID__)
73668a58b8STom Eccles     ret = "/data/local/tmp";
74668a58b8STom Eccles #else
75668a58b8STom Eccles     ret = "/tmp";
76668a58b8STom Eccles #endif
77668a58b8STom Eccles   }
78668a58b8STom Eccles 
79668a58b8STom Eccles   assert(exists(ret));
80668a58b8STom Eccles   return ret;
81668a58b8STom Eccles }
82668a58b8STom Eccles 
83668a58b8STom Eccles static std::string createTemporaryFile(
84668a58b8STom Eccles     const char *name, const AccessType &accessType) {
85668a58b8STom Eccles   std::string path =
86668a58b8STom Eccles       (llvm::Twine{temp_directory_path()} + "/" + addPIDSuffix(name)).str();
87668a58b8STom Eccles 
88668a58b8STom Eccles   // O_CREAT | O_EXCL enforces that this file is newly created by this call.
89668a58b8STom Eccles   // This feels risky. If we don't have permission to create files in the
90668a58b8STom Eccles   // temporary directory or if the files already exist, the test will fail.
91668a58b8STom Eccles   // But we can't use std::tmpfile() because we need a path to the file and
92668a58b8STom Eccles   // to control the filesystem permissions
93668a58b8STom Eccles   mode_t mode{0};
94668a58b8STom Eccles   if (accessType.read) {
95668a58b8STom Eccles     mode |= S_IRUSR;
96668a58b8STom Eccles   }
97668a58b8STom Eccles   if (accessType.write) {
98668a58b8STom Eccles     mode |= S_IWUSR;
99668a58b8STom Eccles   }
100668a58b8STom Eccles   if (accessType.execute) {
101668a58b8STom Eccles     mode |= S_IXUSR;
102668a58b8STom Eccles   }
103668a58b8STom Eccles 
104668a58b8STom Eccles   int file = open(path.c_str(), O_CREAT | O_EXCL, mode);
105668a58b8STom Eccles   if (file == -1) {
106668a58b8STom Eccles     return {};
107668a58b8STom Eccles   }
108668a58b8STom Eccles 
109668a58b8STom Eccles   close(file);
110668a58b8STom Eccles 
111668a58b8STom Eccles   return path;
112668a58b8STom Eccles }
113668a58b8STom Eccles 
114668a58b8STom Eccles static std::int64_t callAccess(
115668a58b8STom Eccles     const std::string &path, const AccessType &accessType) {
116668a58b8STom Eccles   const char *cpath{path.c_str()};
117668a58b8STom Eccles   std::int64_t pathlen = std::strlen(cpath);
118668a58b8STom Eccles 
119668a58b8STom Eccles   std::string mode;
120668a58b8STom Eccles   if (accessType.read) {
121668a58b8STom Eccles     mode += 'r';
122668a58b8STom Eccles   }
123668a58b8STom Eccles   if (accessType.write) {
124668a58b8STom Eccles     mode += 'w';
125668a58b8STom Eccles   }
126668a58b8STom Eccles   if (accessType.execute) {
127668a58b8STom Eccles     mode += 'x';
128668a58b8STom Eccles   }
129668a58b8STom Eccles   if (accessType.exists) {
130668a58b8STom Eccles     mode += ' ';
131668a58b8STom Eccles   }
132668a58b8STom Eccles 
133668a58b8STom Eccles   const char *cmode = mode.c_str();
134668a58b8STom Eccles   std::int64_t modelen = std::strlen(cmode);
135668a58b8STom Eccles 
136668a58b8STom Eccles   return FORTRAN_PROCEDURE_NAME(access)(cpath, pathlen, cmode, modelen);
137668a58b8STom Eccles }
138668a58b8STom Eccles 
139668a58b8STom Eccles TEST(AccessTests, TestExists) {
140668a58b8STom Eccles   AccessType accessType;
141668a58b8STom Eccles   accessType.exists = true;
142668a58b8STom Eccles 
143668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
144668a58b8STom Eccles   ASSERT_FALSE(path.empty());
145668a58b8STom Eccles 
146668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
147668a58b8STom Eccles 
148668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
149668a58b8STom Eccles 
150668a58b8STom Eccles   ASSERT_EQ(res, 0);
151668a58b8STom Eccles }
152668a58b8STom Eccles 
153668a58b8STom Eccles TEST(AccessTests, TestNotExists) {
154668a58b8STom Eccles   std::string nonExistant{addPIDSuffix(__func__)};
155668a58b8STom Eccles   ASSERT_FALSE(exists(nonExistant));
156668a58b8STom Eccles 
157668a58b8STom Eccles   AccessType accessType;
158668a58b8STom Eccles   accessType.exists = true;
159668a58b8STom Eccles   std::int64_t res = callAccess(nonExistant, accessType);
160668a58b8STom Eccles 
161668a58b8STom Eccles   ASSERT_NE(res, 0);
162668a58b8STom Eccles }
163668a58b8STom Eccles 
164668a58b8STom Eccles TEST(AccessTests, TestRead) {
165668a58b8STom Eccles   AccessType accessType;
166668a58b8STom Eccles   accessType.read = true;
167668a58b8STom Eccles 
168668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
169668a58b8STom Eccles   ASSERT_FALSE(path.empty());
170668a58b8STom Eccles 
171668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
172668a58b8STom Eccles 
173668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
174668a58b8STom Eccles 
175*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
176*32403f79STom Eccles     return;
177*32403f79STom Eccles   }
178*32403f79STom Eccles 
179668a58b8STom Eccles   ASSERT_EQ(res, 0);
180668a58b8STom Eccles }
181668a58b8STom Eccles 
182668a58b8STom Eccles TEST(AccessTests, TestNotRead) {
183668a58b8STom Eccles   AccessType accessType;
184668a58b8STom Eccles   accessType.read = false;
185668a58b8STom Eccles 
186668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
187668a58b8STom Eccles   ASSERT_FALSE(path.empty());
188668a58b8STom Eccles 
189668a58b8STom Eccles   accessType.read = true;
190668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
191668a58b8STom Eccles 
192668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
193668a58b8STom Eccles 
194*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
195*32403f79STom Eccles     return;
196*32403f79STom Eccles   }
197*32403f79STom Eccles 
198668a58b8STom Eccles   ASSERT_NE(res, 0);
199668a58b8STom Eccles }
200668a58b8STom Eccles 
201668a58b8STom Eccles TEST(AccessTests, TestWrite) {
202668a58b8STom Eccles   AccessType accessType;
203668a58b8STom Eccles   accessType.write = true;
204668a58b8STom Eccles 
205668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
206668a58b8STom Eccles   ASSERT_FALSE(path.empty());
207668a58b8STom Eccles 
208668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
209668a58b8STom Eccles 
210668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
211668a58b8STom Eccles 
212*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
213*32403f79STom Eccles     return;
214*32403f79STom Eccles   }
215*32403f79STom Eccles 
216668a58b8STom Eccles   ASSERT_EQ(res, 0);
217668a58b8STom Eccles }
218668a58b8STom Eccles 
219668a58b8STom Eccles TEST(AccessTests, TestNotWrite) {
220668a58b8STom Eccles   AccessType accessType;
221668a58b8STom Eccles   accessType.write = false;
222668a58b8STom Eccles 
223668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
224668a58b8STom Eccles   ASSERT_FALSE(path.empty());
225668a58b8STom Eccles 
226668a58b8STom Eccles   accessType.write = true;
227668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
228668a58b8STom Eccles 
229668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
230668a58b8STom Eccles 
231*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
232*32403f79STom Eccles     return;
233*32403f79STom Eccles   }
234*32403f79STom Eccles 
235668a58b8STom Eccles   ASSERT_NE(res, 0);
236668a58b8STom Eccles }
237668a58b8STom Eccles 
238668a58b8STom Eccles TEST(AccessTests, TestReadWrite) {
239668a58b8STom Eccles   AccessType accessType;
240668a58b8STom Eccles   accessType.read = true;
241668a58b8STom Eccles   accessType.write = true;
242668a58b8STom Eccles 
243668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
244668a58b8STom Eccles   ASSERT_FALSE(path.empty());
245668a58b8STom Eccles 
246668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
247668a58b8STom Eccles 
248668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
249668a58b8STom Eccles 
250*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
251*32403f79STom Eccles     return;
252*32403f79STom Eccles   }
253*32403f79STom Eccles 
254668a58b8STom Eccles   ASSERT_EQ(res, 0);
255668a58b8STom Eccles }
256668a58b8STom Eccles 
257668a58b8STom Eccles TEST(AccessTests, TestNotReadWrite0) {
258668a58b8STom Eccles   AccessType accessType;
259668a58b8STom Eccles   accessType.read = false;
260668a58b8STom Eccles   accessType.write = false;
261668a58b8STom Eccles 
262668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
263668a58b8STom Eccles   ASSERT_FALSE(path.empty());
264668a58b8STom Eccles 
265668a58b8STom Eccles   accessType.read = true;
266668a58b8STom Eccles   accessType.write = true;
267668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
268668a58b8STom Eccles 
269668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
270668a58b8STom Eccles 
271*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
272*32403f79STom Eccles     return;
273*32403f79STom Eccles   }
274*32403f79STom Eccles 
275668a58b8STom Eccles   ASSERT_NE(res, 0);
276668a58b8STom Eccles }
277668a58b8STom Eccles 
278668a58b8STom Eccles TEST(AccessTests, TestNotReadWrite1) {
279668a58b8STom Eccles   AccessType accessType;
280668a58b8STom Eccles   accessType.read = true;
281668a58b8STom Eccles   accessType.write = false;
282668a58b8STom Eccles 
283668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
284668a58b8STom Eccles   ASSERT_FALSE(path.empty());
285668a58b8STom Eccles 
286668a58b8STom Eccles   accessType.read = true;
287668a58b8STom Eccles   accessType.write = true;
288668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
289668a58b8STom Eccles 
290668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
291668a58b8STom Eccles 
292*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
293*32403f79STom Eccles     return;
294*32403f79STom Eccles   }
295*32403f79STom Eccles 
296668a58b8STom Eccles   ASSERT_NE(res, 0);
297668a58b8STom Eccles }
298668a58b8STom Eccles 
299668a58b8STom Eccles TEST(AccessTests, TestNotReadWrite2) {
300668a58b8STom Eccles   AccessType accessType;
301668a58b8STom Eccles   accessType.read = false;
302668a58b8STom Eccles   accessType.write = true;
303668a58b8STom Eccles 
304668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
305668a58b8STom Eccles   ASSERT_FALSE(path.empty());
306668a58b8STom Eccles 
307668a58b8STom Eccles   accessType.read = true;
308668a58b8STom Eccles   accessType.write = true;
309668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
310668a58b8STom Eccles 
311668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
312668a58b8STom Eccles 
313*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
314*32403f79STom Eccles     return;
315*32403f79STom Eccles   }
316*32403f79STom Eccles 
317668a58b8STom Eccles   ASSERT_NE(res, 0);
318668a58b8STom Eccles }
319668a58b8STom Eccles 
320668a58b8STom Eccles TEST(AccessTests, TestExecute) {
321668a58b8STom Eccles   AccessType accessType;
322668a58b8STom Eccles   accessType.execute = true;
323668a58b8STom Eccles 
324668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
325668a58b8STom Eccles   ASSERT_FALSE(path.empty());
326668a58b8STom Eccles 
327668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
328668a58b8STom Eccles 
329668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
330668a58b8STom Eccles 
331*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
332*32403f79STom Eccles     return;
333*32403f79STom Eccles   }
334*32403f79STom Eccles 
335668a58b8STom Eccles   ASSERT_EQ(res, 0);
336668a58b8STom Eccles }
337668a58b8STom Eccles 
338668a58b8STom Eccles TEST(AccessTests, TestNotExecute) {
339668a58b8STom Eccles   AccessType accessType;
340668a58b8STom Eccles   accessType.execute = false;
341668a58b8STom Eccles 
342668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
343668a58b8STom Eccles   ASSERT_FALSE(path.empty());
344668a58b8STom Eccles 
345668a58b8STom Eccles   accessType.execute = true;
346668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
347668a58b8STom Eccles 
348668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
349668a58b8STom Eccles 
350*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
351*32403f79STom Eccles     return;
352*32403f79STom Eccles   }
353*32403f79STom Eccles 
354668a58b8STom Eccles   ASSERT_NE(res, 0);
355668a58b8STom Eccles }
356668a58b8STom Eccles 
357668a58b8STom Eccles TEST(AccessTests, TestRWX) {
358668a58b8STom Eccles   AccessType accessType;
359668a58b8STom Eccles   accessType.read = true;
360668a58b8STom Eccles   accessType.write = true;
361668a58b8STom Eccles   accessType.execute = true;
362668a58b8STom Eccles 
363668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
364668a58b8STom Eccles   ASSERT_FALSE(path.empty());
365668a58b8STom Eccles 
366668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
367668a58b8STom Eccles 
368668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
369668a58b8STom Eccles 
370*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
371*32403f79STom Eccles     return;
372*32403f79STom Eccles   }
373*32403f79STom Eccles 
374668a58b8STom Eccles   ASSERT_EQ(res, 0);
375668a58b8STom Eccles }
376668a58b8STom Eccles 
377668a58b8STom Eccles TEST(AccessTests, TestNotRWX0) {
378668a58b8STom Eccles   AccessType accessType;
379668a58b8STom Eccles   accessType.read = false;
380668a58b8STom Eccles   accessType.write = false;
381668a58b8STom Eccles   accessType.execute = false;
382668a58b8STom Eccles 
383668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
384668a58b8STom Eccles   ASSERT_FALSE(path.empty());
385668a58b8STom Eccles 
386668a58b8STom Eccles   accessType.read = true;
387668a58b8STom Eccles   accessType.write = true;
388668a58b8STom Eccles   accessType.execute = true;
389668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
390668a58b8STom Eccles 
391668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
392668a58b8STom Eccles 
393*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
394*32403f79STom Eccles     return;
395*32403f79STom Eccles   }
396*32403f79STom Eccles 
397668a58b8STom Eccles   ASSERT_NE(res, 0);
398668a58b8STom Eccles }
399668a58b8STom Eccles 
400668a58b8STom Eccles TEST(AccessTests, TestNotRWX1) {
401668a58b8STom Eccles   AccessType accessType;
402668a58b8STom Eccles   accessType.read = true;
403668a58b8STom Eccles   accessType.write = false;
404668a58b8STom Eccles   accessType.execute = false;
405668a58b8STom Eccles 
406668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
407668a58b8STom Eccles   ASSERT_FALSE(path.empty());
408668a58b8STom Eccles 
409668a58b8STom Eccles   accessType.read = true;
410668a58b8STom Eccles   accessType.write = true;
411668a58b8STom Eccles   accessType.execute = true;
412668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
413668a58b8STom Eccles 
414668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
415668a58b8STom Eccles 
416*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
417*32403f79STom Eccles     return;
418*32403f79STom Eccles   }
419*32403f79STom Eccles 
420668a58b8STom Eccles   ASSERT_NE(res, 0);
421668a58b8STom Eccles }
422668a58b8STom Eccles 
423668a58b8STom Eccles TEST(AccessTests, TestNotRWX2) {
424668a58b8STom Eccles   AccessType accessType;
425668a58b8STom Eccles   accessType.read = true;
426668a58b8STom Eccles   accessType.write = true;
427668a58b8STom Eccles   accessType.execute = false;
428668a58b8STom Eccles 
429668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
430668a58b8STom Eccles   ASSERT_FALSE(path.empty());
431668a58b8STom Eccles 
432668a58b8STom Eccles   accessType.read = true;
433668a58b8STom Eccles   accessType.write = true;
434668a58b8STom Eccles   accessType.execute = true;
435668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
436668a58b8STom Eccles 
437668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
438668a58b8STom Eccles 
439*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
440*32403f79STom Eccles     return;
441*32403f79STom Eccles   }
442*32403f79STom Eccles 
443668a58b8STom Eccles   ASSERT_NE(res, 0);
444668a58b8STom Eccles }
445668a58b8STom Eccles 
446668a58b8STom Eccles TEST(AccessTests, TestNotRWX3) {
447668a58b8STom Eccles   AccessType accessType;
448668a58b8STom Eccles   accessType.read = true;
449668a58b8STom Eccles   accessType.write = false;
450668a58b8STom Eccles   accessType.execute = true;
451668a58b8STom Eccles 
452668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
453668a58b8STom Eccles   ASSERT_FALSE(path.empty());
454668a58b8STom Eccles 
455668a58b8STom Eccles   accessType.read = true;
456668a58b8STom Eccles   accessType.write = true;
457668a58b8STom Eccles   accessType.execute = true;
458668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
459668a58b8STom Eccles 
460668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
461668a58b8STom Eccles 
462*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
463*32403f79STom Eccles     return;
464*32403f79STom Eccles   }
465*32403f79STom Eccles 
466668a58b8STom Eccles   ASSERT_NE(res, 0);
467668a58b8STom Eccles }
468668a58b8STom Eccles 
469668a58b8STom Eccles TEST(AccessTests, TestNotRWX4) {
470668a58b8STom Eccles   AccessType accessType;
471668a58b8STom Eccles   accessType.read = false;
472668a58b8STom Eccles   accessType.write = true;
473668a58b8STom Eccles   accessType.execute = true;
474668a58b8STom Eccles 
475668a58b8STom Eccles   std::string path = createTemporaryFile(__func__, accessType);
476668a58b8STom Eccles   ASSERT_FALSE(path.empty());
477668a58b8STom Eccles 
478668a58b8STom Eccles   accessType.read = true;
479668a58b8STom Eccles   accessType.write = true;
480668a58b8STom Eccles   accessType.execute = true;
481668a58b8STom Eccles   std::int64_t res = callAccess(path, accessType);
482668a58b8STom Eccles 
483668a58b8STom Eccles   ASSERT_EQ(unlink(path.c_str()), 0);
484668a58b8STom Eccles 
485*32403f79STom Eccles   if (userSkipsPermissionChecks()) {
486*32403f79STom Eccles     return;
487*32403f79STom Eccles   }
488*32403f79STom Eccles 
489668a58b8STom Eccles   ASSERT_NE(res, 0);
490668a58b8STom Eccles }
491668a58b8STom Eccles 
492668a58b8STom Eccles #endif // !_WIN32
493