forked from OSchip/llvm-project
[libc] Add implementations of feof, ferror and clearerr.
The corresponding _unlocked functions have also been added. Reviewed By: lntue, michaelrj Differential Revision: https://reviews.llvm.org/D124311
This commit is contained in:
parent
97b8a54b25
commit
9db0037bf1
|
@ -251,8 +251,14 @@ if(LLVM_LIBC_FULL_BUILD)
|
|||
libc.src.stdlib.getenv
|
||||
|
||||
# stdio.h entrypoints
|
||||
libc.src.stdio.clearerr
|
||||
libc.src.stdio.clearerr_unlocked
|
||||
libc.src.stdio.fclose
|
||||
libc.src.stdio.flockfile
|
||||
libc.src.stdio.feof
|
||||
libc.src.stdio.feof_unlocked
|
||||
libc.src.stdio.ferror
|
||||
libc.src.stdio.ferror_unlocked
|
||||
libc.src.stdio.fflush
|
||||
libc.src.stdio.fopen
|
||||
libc.src.stdio.fopencookie
|
||||
|
|
|
@ -72,6 +72,21 @@ def GnuExtensions : StandardSpec<"GNUExtensions"> {
|
|||
[CookieIOFunctionsT], // Types
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
"clearerr_unlocked",
|
||||
RetValSpec<VoidType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"feof_unlocked",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"ferror_unlocked",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fopencookie",
|
||||
RetValSpec<FILEPtr>,
|
||||
|
|
|
@ -478,11 +478,26 @@ def StdC : StandardSpec<"stdc"> {
|
|||
],
|
||||
[], // Enumerations
|
||||
[
|
||||
FunctionSpec<
|
||||
"clearerr",
|
||||
RetValSpec<VoidType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fclose",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"feof",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"ferror",
|
||||
RetValSpec<IntType>,
|
||||
[ArgSpec<FILEPtr>]
|
||||
>,
|
||||
FunctionSpec<
|
||||
"fflush",
|
||||
RetValSpec<IntType>,
|
||||
|
|
|
@ -97,6 +97,19 @@ private:
|
|||
bool eof;
|
||||
bool err;
|
||||
|
||||
// This is a convenience RAII class to lock and unlock file objects.
|
||||
class FileLock {
|
||||
File *file;
|
||||
|
||||
public:
|
||||
explicit FileLock(File *f) : file(f) { file->lock(); }
|
||||
|
||||
~FileLock() { file->unlock(); }
|
||||
|
||||
FileLock(const FileLock &) = delete;
|
||||
FileLock(FileLock &&) = delete;
|
||||
};
|
||||
|
||||
protected:
|
||||
bool write_allowed() const {
|
||||
return mode & (static_cast<ModeFlags>(OpenMode::WRITE) |
|
||||
|
@ -150,10 +163,8 @@ public:
|
|||
|
||||
// Buffered write of |len| bytes from |data| under the file lock.
|
||||
size_t write(const void *data, size_t len) {
|
||||
lock();
|
||||
size_t ret = write_unlocked(data, len);
|
||||
unlock();
|
||||
return ret;
|
||||
FileLock l(this);
|
||||
return write_unlocked(data, len);
|
||||
}
|
||||
|
||||
// Buffered read of |len| bytes into |data| without the file lock.
|
||||
|
@ -161,10 +172,8 @@ public:
|
|||
|
||||
// Buffered read of |len| bytes into |data| under the file lock.
|
||||
size_t read(void *data, size_t len) {
|
||||
lock();
|
||||
size_t ret = read_unlocked(data, len);
|
||||
unlock();
|
||||
return ret;
|
||||
FileLock l(this);
|
||||
return read_unlocked(data, len);
|
||||
}
|
||||
|
||||
int seek(long offset, int whence);
|
||||
|
@ -184,28 +193,32 @@ public:
|
|||
void lock() { mutex.lock(); }
|
||||
void unlock() { mutex.unlock(); }
|
||||
|
||||
bool error() const { return err; }
|
||||
void clearerr() { err = false; }
|
||||
bool iseof() const { return eof; }
|
||||
bool error_unlocked() const { return err; }
|
||||
|
||||
bool error() {
|
||||
FileLock l(this);
|
||||
return error_unlocked();
|
||||
}
|
||||
|
||||
void clearerr_unlocked() { err = false; }
|
||||
|
||||
void clearerr() {
|
||||
FileLock l(this);
|
||||
clearerr_unlocked();
|
||||
}
|
||||
|
||||
bool iseof_unlocked() { return eof; }
|
||||
|
||||
bool iseof() {
|
||||
FileLock l(this);
|
||||
return iseof_unlocked();
|
||||
}
|
||||
|
||||
// Returns an bit map of flags corresponding to enumerations of
|
||||
// OpenMode, ContentType and CreateType.
|
||||
static ModeFlags mode_flags(const char *mode);
|
||||
};
|
||||
|
||||
// This is a convenience RAII class to lock and unlock file objects.
|
||||
class FileLock {
|
||||
File *file;
|
||||
|
||||
public:
|
||||
explicit FileLock(File *f) : file(f) { file->lock(); }
|
||||
|
||||
~FileLock() { file->unlock(); }
|
||||
|
||||
FileLock(const FileLock &) = delete;
|
||||
FileLock(FileLock &&) = delete;
|
||||
};
|
||||
|
||||
// The implementaiton of this function is provided by the platfrom_file
|
||||
// library.
|
||||
File *openfile(const char *path, const char *mode);
|
||||
|
|
|
@ -24,6 +24,78 @@ add_entrypoint_object(
|
|||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
clearerr
|
||||
SRCS
|
||||
clearerr.cpp
|
||||
HDRS
|
||||
clearerr.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
clearerr_unlocked
|
||||
SRCS
|
||||
clearerr_unlocked.cpp
|
||||
HDRS
|
||||
clearerr_unlocked.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
feof
|
||||
SRCS
|
||||
feof.cpp
|
||||
HDRS
|
||||
feof.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
feof_unlocked
|
||||
SRCS
|
||||
feof_unlocked.cpp
|
||||
HDRS
|
||||
feof_unlocked.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
ferror
|
||||
SRCS
|
||||
ferror.cpp
|
||||
HDRS
|
||||
ferror.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
ferror_unlocked
|
||||
SRCS
|
||||
ferror_unlocked.cpp
|
||||
HDRS
|
||||
ferror_unlocked.h
|
||||
DEPENDS
|
||||
libc.include.stdio
|
||||
libc.src.__support.File.file
|
||||
libc.src.__support.File.platform_file
|
||||
)
|
||||
|
||||
add_entrypoint_object(
|
||||
fflush
|
||||
SRCS
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of clearerr ----------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/clearerr.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(void, clearerr, (::FILE * stream)) {
|
||||
reinterpret_cast<__llvm_libc::File *>(stream)->clearerr();
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of clearerr -----------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_CLEARERR_H
|
||||
#define LLVM_LIBC_SRC_STDIO_CLEARERR_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
void clearerr(::FILE *stream);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_CLEARERR_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of clearerr_unlocked -------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/clearerr_unlocked.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(void, clearerr_unlocked, (::FILE * stream)) {
|
||||
reinterpret_cast<__llvm_libc::File *>(stream)->clearerr_unlocked();
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of clearerr_unlocked --------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_CLEARERR_UNLOCKED_H
|
||||
#define LLVM_LIBC_SRC_STDIO_CLEARERR_UNLOCKED_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
void clearerr_unlocked(::FILE *stream);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_CLEARERR_UNLOCKED_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of feof --------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/feof.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, feof, (::FILE * stream)) {
|
||||
return reinterpret_cast<__llvm_libc::File *>(stream)->iseof();
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of feof ---------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_FEOF_H
|
||||
#define LLVM_LIBC_SRC_STDIO_FEOF_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int feof(::FILE *stream);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_FEOF_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of feof_unlocked -----------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/feof_unlocked.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, feof_unlocked, (::FILE * stream)) {
|
||||
return reinterpret_cast<__llvm_libc::File *>(stream)->iseof_unlocked();
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of feof_unlocked ------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_FEOF_UNLOCKED_H
|
||||
#define LLVM_LIBC_SRC_STDIO_FEOF_UNLOCKED_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int feof_unlocked(::FILE *stream);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_FEOF_UNLOCKED_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of ferror ------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/ferror.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, ferror, (::FILE * stream)) {
|
||||
return reinterpret_cast<__llvm_libc::File *>(stream)->error();
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of ferror -------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_FERROR_H
|
||||
#define LLVM_LIBC_SRC_STDIO_FERROR_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int ferror(::FILE *stream);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_FERROR_H
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation of ferror_unlocked ---------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/ferror_unlocked.h"
|
||||
#include "src/__support/File/file.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
LLVM_LIBC_FUNCTION(int, ferror_unlocked, (::FILE * stream)) {
|
||||
return reinterpret_cast<__llvm_libc::File *>(stream)->error_unlocked();
|
||||
}
|
||||
|
||||
} // namespace __llvm_libc
|
|
@ -0,0 +1,20 @@
|
|||
//===-- Implementation header of ferror_unlocked ----------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_STDIO_FERROR_UNLOCKED_H
|
||||
#define LLVM_LIBC_SRC_STDIO_FERROR_UNLOCKED_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
namespace __llvm_libc {
|
||||
|
||||
int ferror_unlocked(::FILE *stream);
|
||||
|
||||
} // namespace __llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_STDIO_FERROR_UNLOCKED_H
|
|
@ -7,7 +7,12 @@ add_libc_unittest(
|
|||
SRCS
|
||||
fileop_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.stdio
|
||||
libc.src.stdio.clearerr
|
||||
libc.src.stdio.fclose
|
||||
libc.src.stdio.feof
|
||||
libc.src.stdio.ferror
|
||||
libc.src.stdio.fflush
|
||||
libc.src.stdio.fopen
|
||||
libc.src.stdio.fread
|
||||
|
@ -22,7 +27,12 @@ add_libc_unittest(
|
|||
SRCS
|
||||
unlocked_fileop_test.cpp
|
||||
DEPENDS
|
||||
libc.include.errno
|
||||
libc.include.stdio
|
||||
libc.src.stdio.clearerr_unlocked
|
||||
libc.src.stdio.fclose
|
||||
libc.src.stdio.feof_unlocked
|
||||
libc.src.stdio.ferror_unlocked
|
||||
libc.src.stdio.flockfile
|
||||
libc.src.stdio.fopen
|
||||
libc.src.stdio.fread_unlocked
|
||||
|
@ -40,7 +50,10 @@ add_libc_unittest(
|
|||
libc.include.errno
|
||||
libc.include.stdio
|
||||
libc.include.stdlib
|
||||
libc.src.stdio.clearerr
|
||||
libc.src.stdio.fclose
|
||||
libc.src.stdio.feof
|
||||
libc.src.stdio.ferror
|
||||
libc.src.stdio.fflush
|
||||
libc.src.stdio.fopencookie
|
||||
libc.src.stdio.fread
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/clearerr.h"
|
||||
#include "src/stdio/fclose.h"
|
||||
#include "src/stdio/feof.h"
|
||||
#include "src/stdio/ferror.h"
|
||||
#include "src/stdio/fflush.h"
|
||||
#include "src/stdio/fopen.h"
|
||||
#include "src/stdio/fread.h"
|
||||
|
@ -14,15 +17,27 @@
|
|||
#include "src/stdio/fwrite.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
TEST(LlvmLibcStdio, SimpleOperations) {
|
||||
TEST(LlvmLibcFILETest, SimpleFileOperations) {
|
||||
constexpr char FILENAME[] = "testdata/simple_operations.test";
|
||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
constexpr char CONTENT[] = "1234567890987654321";
|
||||
ASSERT_EQ(sizeof(CONTENT) - 1,
|
||||
__llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT) - 1, file));
|
||||
|
||||
// This is not a readable file.
|
||||
char read_data[sizeof(CONTENT)];
|
||||
ASSERT_EQ(__llvm_libc::fread(read_data, 1, sizeof(CONTENT), file), size_t(0));
|
||||
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||
EXPECT_NE(errno, 0);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr(file);
|
||||
ASSERT_EQ(__llvm_libc::ferror(file), 0);
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
|
||||
file = __llvm_libc::fopen(FILENAME, "r");
|
||||
|
@ -40,10 +55,24 @@ TEST(LlvmLibcStdio, SimpleOperations) {
|
|||
ASSERT_EQ(__llvm_libc::fread(data, 1, READ_SIZE - 1, file), READ_SIZE - 1);
|
||||
ASSERT_STREQ(data, "9098");
|
||||
|
||||
// Reading another time should trigger eof.
|
||||
ASSERT_NE(sizeof(CONTENT),
|
||||
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), file));
|
||||
ASSERT_NE(__llvm_libc::feof(file), 0);
|
||||
|
||||
// Should be an error to write.
|
||||
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), file));
|
||||
ASSERT_NE(__llvm_libc::ferror(file), 0);
|
||||
ASSERT_NE(errno, 0);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr(file);
|
||||
ASSERT_EQ(__llvm_libc::ferror(file), 0);
|
||||
|
||||
ASSERT_EQ(__llvm_libc::fclose(file), 0);
|
||||
}
|
||||
|
||||
TEST(LlvmLibcFILE, FFlushTest) {
|
||||
TEST(LlvmLibcFILETest, FFlush) {
|
||||
constexpr char FILENAME[] = "testdata/fflush.test";
|
||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w+");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
|
|
|
@ -6,7 +6,10 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/clearerr.h"
|
||||
#include "src/stdio/fclose.h"
|
||||
#include "src/stdio/feof.h"
|
||||
#include "src/stdio/ferror.h"
|
||||
#include "src/stdio/fflush.h"
|
||||
#include "src/stdio/fopencookie.h"
|
||||
#include "src/stdio/fread.h"
|
||||
|
@ -102,12 +105,21 @@ TEST(LlvmLibcFOpenCookie, ReadOnlyCookieTest) {
|
|||
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), f));
|
||||
ASSERT_STREQ(read_data, CONTENT);
|
||||
|
||||
// Reading another time should trigger eof.
|
||||
ASSERT_NE(sizeof(CONTENT),
|
||||
__llvm_libc::fread(read_data, 1, sizeof(CONTENT), f));
|
||||
ASSERT_NE(__llvm_libc::feof(f), 0);
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fseek(f, 0, SEEK_SET));
|
||||
// Should be an error to write.
|
||||
ASSERT_EQ(size_t(0), __llvm_libc::fwrite(CONTENT, 1, sizeof(CONTENT), f));
|
||||
ASSERT_EQ(errno, EBADF);
|
||||
ASSERT_NE(__llvm_libc::ferror(f), 0);
|
||||
ASSERT_NE(errno, 0);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr(f);
|
||||
ASSERT_EQ(__llvm_libc::ferror(f), 0);
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
||||
free(ss);
|
||||
}
|
||||
|
@ -134,9 +146,13 @@ TEST(LlvmLibcFOpenCookie, WriteOnlyCookieTest) {
|
|||
char read_data[sizeof(WRITE_DATA)];
|
||||
// Should be an error to read.
|
||||
ASSERT_EQ(size_t(0), __llvm_libc::fread(read_data, 1, sizeof(WRITE_DATA), f));
|
||||
ASSERT_NE(__llvm_libc::ferror(f), 0);
|
||||
ASSERT_EQ(errno, EBADF);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr(f);
|
||||
ASSERT_EQ(__llvm_libc::ferror(f), 0);
|
||||
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
||||
free(ss);
|
||||
}
|
||||
|
@ -159,9 +175,13 @@ TEST(LlvmLibcFOpenCookie, AppendOnlyCookieTest) {
|
|||
char read_data[READ_SIZE];
|
||||
// This is not a readable file.
|
||||
ASSERT_EQ(__llvm_libc::fread(read_data, 1, READ_SIZE, f), size_t(0));
|
||||
ASSERT_NE(__llvm_libc::ferror(f), 0);
|
||||
EXPECT_NE(errno, 0);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr(f);
|
||||
ASSERT_EQ(__llvm_libc::ferror(f), 0);
|
||||
|
||||
ASSERT_EQ(__llvm_libc::fwrite(WRITE_DATA, 1, sizeof(WRITE_DATA), f),
|
||||
sizeof(WRITE_DATA));
|
||||
EXPECT_EQ(__llvm_libc::fflush(f), 0);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//===-- Unittests for file operations like fopen, flcose etc --------------===//
|
||||
//===-- Unittests for f operations like fopen, flcose etc --------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -6,7 +6,10 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/stdio/clearerr_unlocked.h"
|
||||
#include "src/stdio/fclose.h"
|
||||
#include "src/stdio/feof_unlocked.h"
|
||||
#include "src/stdio/ferror_unlocked.h"
|
||||
#include "src/stdio/flockfile.h"
|
||||
#include "src/stdio/fopen.h"
|
||||
#include "src/stdio/fread_unlocked.h"
|
||||
|
@ -14,31 +17,60 @@
|
|||
#include "src/stdio/fwrite_unlocked.h"
|
||||
#include "utils/UnitTest/Test.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
TEST(LlvmLibcFILETest, UnlockedReadAndWrite) {
|
||||
constexpr char FILENAME[] = "testdata/unlocked_read_and_write.test";
|
||||
::FILE *file = __llvm_libc::fopen(FILENAME, "w");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
constexpr char fNAME[] = "testdata/unlocked_read_and_write.test";
|
||||
::FILE *f = __llvm_libc::fopen(fNAME, "w");
|
||||
ASSERT_FALSE(f == nullptr);
|
||||
constexpr char CONTENT[] = "1234567890987654321";
|
||||
__llvm_libc::flockfile(file);
|
||||
ASSERT_EQ(sizeof(CONTENT) - 1, __llvm_libc::fwrite_unlocked(
|
||||
CONTENT, 1, sizeof(CONTENT) - 1, file));
|
||||
__llvm_libc::funlockfile(file);
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(file));
|
||||
|
||||
file = __llvm_libc::fopen(FILENAME, "r");
|
||||
ASSERT_FALSE(file == nullptr);
|
||||
|
||||
__llvm_libc::flockfile(f);
|
||||
ASSERT_EQ(sizeof(CONTENT) - 1,
|
||||
__llvm_libc::fwrite_unlocked(CONTENT, 1, sizeof(CONTENT) - 1, f));
|
||||
// Should be an error to read.
|
||||
constexpr size_t READ_SIZE = 5;
|
||||
char data[READ_SIZE * 2 + 1];
|
||||
data[READ_SIZE * 2] = '\0';
|
||||
__llvm_libc::flockfile(file);
|
||||
ASSERT_EQ(__llvm_libc::fread_unlocked(data, 1, READ_SIZE, file), READ_SIZE);
|
||||
ASSERT_EQ(__llvm_libc::fread_unlocked(data + READ_SIZE, 1, READ_SIZE, file),
|
||||
|
||||
ASSERT_EQ(size_t(0),
|
||||
__llvm_libc::fread_unlocked(data, 1, sizeof(READ_SIZE), f));
|
||||
ASSERT_NE(__llvm_libc::ferror_unlocked(f), 0);
|
||||
ASSERT_NE(errno, 0);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr_unlocked(f);
|
||||
ASSERT_EQ(__llvm_libc::ferror_unlocked(f), 0);
|
||||
|
||||
__llvm_libc::funlockfile(f);
|
||||
ASSERT_EQ(0, __llvm_libc::fclose(f));
|
||||
|
||||
f = __llvm_libc::fopen(fNAME, "r");
|
||||
ASSERT_FALSE(f == nullptr);
|
||||
|
||||
__llvm_libc::flockfile(f);
|
||||
ASSERT_EQ(__llvm_libc::fread_unlocked(data, 1, READ_SIZE, f), READ_SIZE);
|
||||
ASSERT_EQ(__llvm_libc::fread_unlocked(data + READ_SIZE, 1, READ_SIZE, f),
|
||||
READ_SIZE);
|
||||
__llvm_libc::funlockfile(file);
|
||||
|
||||
// Should be an error to write.
|
||||
ASSERT_EQ(size_t(0),
|
||||
__llvm_libc::fwrite_unlocked(CONTENT, 1, sizeof(CONTENT), f));
|
||||
ASSERT_NE(__llvm_libc::ferror_unlocked(f), 0);
|
||||
ASSERT_NE(errno, 0);
|
||||
errno = 0;
|
||||
|
||||
__llvm_libc::clearerr_unlocked(f);
|
||||
ASSERT_EQ(__llvm_libc::ferror_unlocked(f), 0);
|
||||
|
||||
// Reading more should trigger eof.
|
||||
char large_data[sizeof(CONTENT)];
|
||||
ASSERT_NE(sizeof(CONTENT),
|
||||
__llvm_libc::fread_unlocked(large_data, 1, sizeof(CONTENT), f));
|
||||
ASSERT_NE(__llvm_libc::feof_unlocked(f), 0);
|
||||
|
||||
__llvm_libc::funlockfile(f);
|
||||
ASSERT_STREQ(data, "1234567890");
|
||||
|
||||
ASSERT_EQ(__llvm_libc::fclose(file), 0);
|
||||
ASSERT_EQ(__llvm_libc::fclose(f), 0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue