141 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// XFAIL: availability-fp_to_chars-missing14 15// The error exception has no system error string.16// XFAIL: LIBCXX-ANDROID-FIXME17 18// <print>19 20// template<class... Args>21// void print(FILE* stream, format_string<Args...> fmt, Args&&... args);22 23// In the library when the stdout is redirected to a file it is no24// longer considered a terminal and the special terminal handling is no25// longer executed. There are tests in26// libcxx/test/libcxx/input.output/iostream.format/print.fun/27// to validate that behaviour28 29#include <algorithm>30#include <array>31#include <cassert>32#include <cstddef>33#include <cstdio>34#include <fstream>35#include <iterator>36#include <print>37#include <string_view>38 39#include "assert_macros.h"40#include "concat_macros.h"41#include "filesystem_test_helper.h"42#include "print_tests.h"43#include "test_format_string.h"44#include "test_macros.h"45 46scoped_test_env env;47std::string filename = env.create_file("output.txt");48 49auto test_file = []<class... Args>(std::string_view expected, test_format_string<char, Args...> fmt, Args&&... args) {50 FILE* file = fopen(filename.c_str(), "wb");51 assert(file);52 53 std::print(file, fmt, std::forward<Args>(args)...);54 std::fclose(file);55 56 std::ifstream stream{filename.c_str(), std::ios_base::in | std::ios_base::binary};57 std::string out(std::istreambuf_iterator<char>{stream}, {});58 TEST_REQUIRE(out == expected,59 TEST_WRITE_CONCATENATED(60 "\nFormat string ", fmt.get(), "\nExpected output ", expected, "\nActual output ", out, '\n'));61};62 63auto test_exception = []<class... Args>(std::string_view, std::string_view, Args&&...) {64 // After P2216 most exceptions thrown by std::format become ill-formed.65 // Therefore this tests does nothing.66 // A basic ill-formed test is done in format.verify.cpp67 // The exceptions are tested by other functions that don't use the basic-format-string as fmt argument.68};69 70// Glibc fails writing to a wide stream.71#if defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)72static void test_wide_stream() {73 FILE* file = fopen(filename.c_str(), "wb");74 assert(file);75 76 int mode = std::fwide(file, 1);77 assert(mode > 0);78 79 TEST_VALIDATE_EXCEPTION(80 std::system_error,81 [&]([[maybe_unused]] const std::system_error& e) {82 [[maybe_unused]] std::string_view what{"failed to write formatted output"};83 TEST_LIBCPP_REQUIRE(84 e.what() == what,85 TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));86 },87 std::print(file, "hello"));88}89#endif // defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)90 91static void test_read_only() {92 FILE* file = fopen(filename.c_str(), "r");93 assert(file);94 95 TEST_VALIDATE_EXCEPTION(96 std::system_error,97 [&]([[maybe_unused]] const std::system_error& e) {98 [[maybe_unused]] std::string_view what{99 "failed to write formatted output: " TEST_IF_AIX("Broken pipe", "Operation not permitted")};100 TEST_LIBCPP_REQUIRE(101 e.what() == what,102 TEST_WRITE_CONCATENATED("\nExpected exception ", what, "\nActual exception ", e.what(), '\n'));103 },104 std::print(file, "hello"));105}106 107static void test_new_line() {108 // Text does newline translation.109 {110 FILE* file = fopen(filename.c_str(), "w");111 assert(file);112 113 std::print(file, "\n");114#ifndef _WIN32115 assert(std::ftell(file) == 1);116#else117 assert(std::ftell(file) == 2);118#endif119 }120 // Binary no newline translation.121 {122 FILE* file = fopen(filename.c_str(), "wb");123 assert(file);124 125 std::print(file, "\n");126 assert(std::ftell(file) == 1);127 }128}129 130int main(int, char**) {131 print_tests(test_file, test_exception);132 133#if defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)134 test_wide_stream();135#endif136 test_read_only();137 test_new_line();138 139 return 0;140}141