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-exception
6//
7//===----------------------------------------------------------------------===//
8
9// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
10// UNSUPPORTED: no-filesystem
11// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
12
13// TODO PRINT Enable again
14// https://reviews.llvm.org/D150044
15// https://lab.llvm.org/buildbot/#/builders/237/builds/3578
16// UNSUPPORTED: asan, hwasan, msan
17
18// XFAIL: availability-fp_to_chars-missing
19
20// The error exception has no system error string.
21// XFAIL: LIBCXX-ANDROID-FIXME
22
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: filename.c_str(), modes: "wb");
48 assert(file);
49
50 std::vprint_nonunicode(file, fmt, std::make_format_args(args...));
51 std::fclose(stream: 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: filename.c_str(), modes: "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(stream: 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: filename.c_str(), modes: "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: filename.c_str(), modes: "w");
120 assert(file);
121
122 std::vprint_nonunicode(file, "\n", std::make_format_args());
123#ifndef _WIN32
124 assert(std::ftell(file) == 1);
125#else
126 assert(std::ftell(file) == 2);
127#endif
128 }
129 // Binary no newline translation.
130 {
131 FILE* file = fopen(filename: filename.c_str(), modes: "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(check: test_file, check_exception: test_exception);
141
142#if defined(TEST_HAS_GLIBC) && !defined(TEST_HAS_NO_WIDE_CHARACTERS)
143 test_wide_stream();
144#endif
145 test_read_only();
146 test_new_line();
147
148 return 0;
149}
150

source code of libcxx/test/std/input.output/iostream.format/print.fun/vprint_nonunicode.file.pass.cpp