150 lines · cpp
1//===----------------------------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++2010// UNSUPPORTED: no-filesystem11// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME12 13// TODO PRINT Enable again14// https://reviews.llvm.org/D15004415// https://lab.llvm.org/buildbot/#/builders/237/builds/357816// UNSUPPORTED: asan, hwasan, msan17 18// XFAIL: availability-fp_to_chars-missing19 20// The error exception has no system error string.21// XFAIL: LIBCXX-ANDROID-FIXME22 23// <print>24 25// void vprint_nonunicode(FILE* stream, string_view fmt, format_args args);26 27#include <algorithm>28#include <array>29#include <cassert>30#include <cstddef>31#include <cstdio>32#include <fstream>33#include <iterator>34#include <print>35#include <string_view>36 37#include "assert_macros.h"38#include "concat_macros.h"39#include "filesystem_test_helper.h"40#include "print_tests.h"41#include "test_macros.h"42 43scoped_test_env env;44std::string filename = env.create_file("output.txt");45 46auto test_file = []<class... Args>(std::string_view expected, std::string_view fmt, Args&&... args) {47 FILE* file = fopen(filename.c_str(), "wb");48 assert(file);49 50 std::vprint_nonunicode(file, fmt, std::make_format_args(args...));51 std::fclose(file);52 53 std::ifstream stream{filename.c_str(), std::ios_base::in | std::ios_base::binary};54 std::string out(std::istreambuf_iterator<char>{stream}, {});55 TEST_REQUIRE(out == expected,56 TEST_WRITE_CONCATENATED(57 "\nFormat string ", fmt, "\nExpected output ", expected, "\nActual output ", out, '\n'));58};59 60auto test_exception = []<class... Args>([[maybe_unused]] std::string_view what,61 [[maybe_unused]] std::string_view fmt,62 [[maybe_unused]] Args&&... args) {63 FILE* file = fopen(filename.c_str(), "wb");64 assert(file);65 66 TEST_VALIDATE_EXCEPTION(67 std::format_error,68 [&]([[maybe_unused]] const std::format_error& e) {69 TEST_LIBCPP_REQUIRE(70 e.what() == what,71 TEST_WRITE_CONCATENATED(72 "\nFormat string ", fmt, "\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));73 },74 std::vprint_nonunicode(file, fmt, std::make_format_args(args...)));75 76 fclose(file);77};78 79// Glibc fails writing to a wide stream.80#if defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)81static void test_wide_stream() {82 FILE* file = fopen(filename.c_str(), "wb");83 assert(file);84 85 int mode = std::fwide(file, 1);86 assert(mode > 0);87 88 TEST_VALIDATE_EXCEPTION(89 std::system_error,90 [&]([[maybe_unused]] const std::system_error& e) {91 [[maybe_unused]] std::string_view what{"failed to write formatted output"};92 TEST_LIBCPP_REQUIRE(93 e.what() == what,94 TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));95 },96 std::vprint_nonunicode(file, "hello", std::make_format_args()));97}98#endif // defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)99 100static void test_read_only() {101 FILE* file = fopen(filename.c_str(), "r");102 assert(file);103 104 TEST_VALIDATE_EXCEPTION(105 std::system_error,106 [&]([[maybe_unused]] const std::system_error& e) {107 [[maybe_unused]] std::string_view what{108 "failed to write formatted output: " TEST_IF_AIX("Broken pipe", "Operation not permitted")};109 TEST_LIBCPP_REQUIRE(110 e.what() == what,111 TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));112 },113 std::vprint_nonunicode(file, "hello", std::make_format_args()));114}115 116static void test_new_line() {117 // Text does newline translation.118 {119 FILE* file = fopen(filename.c_str(), "w");120 assert(file);121 122 std::vprint_nonunicode(file, "\n", std::make_format_args());123#ifndef _WIN32124 assert(std::ftell(file) == 1);125#else126 assert(std::ftell(file) == 2);127#endif128 }129 // Binary no newline translation.130 {131 FILE* file = fopen(filename.c_str(), "wb");132 assert(file);133 134 std::vprint_nonunicode(file, "\n", std::make_format_args());135 assert(std::ftell(file) == 1);136 }137}138 139int main(int, char**) {140 print_tests(test_file, test_exception);141 142#if defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)143 test_wide_stream();144#endif145 test_read_only();146 test_new_line();147 148 return 0;149}150