[PowerPC][NFC] Cleanup PPCCTRLoopsVerify pass
[llvm-project.git] / flang / unittests / Runtime / format.cpp
blob87989eacebcbecaaaadcd3f9aed3d71a4086c55f
1 // Tests basic FORMAT string traversal
3 #include "testing.h"
4 #include "../runtime/format-implementation.h"
5 #include "../runtime/io-error.h"
6 #include <cstdarg>
7 #include <cstring>
8 #include <string>
9 #include <vector>
11 using namespace Fortran::runtime;
12 using namespace Fortran::runtime::io;
13 using namespace std::literals::string_literals;
15 using Results = std::vector<std::string>;
17 // A test harness context for testing FormatControl
18 class TestFormatContext : public IoErrorHandler {
19 public:
20 using CharType = char;
21 TestFormatContext() : IoErrorHandler{"format.cpp", 1} {}
22 bool Emit(const char *, std::size_t);
23 bool Emit(const char16_t *, std::size_t);
24 bool Emit(const char32_t *, std::size_t);
25 bool AdvanceRecord(int = 1);
26 void HandleRelativePosition(std::int64_t);
27 void HandleAbsolutePosition(std::int64_t);
28 void Report(const DataEdit &);
29 void Check(Results &);
30 Results results;
31 MutableModes &mutableModes() { return mutableModes_; }
33 private:
34 MutableModes mutableModes_;
37 bool TestFormatContext::Emit(const char *s, std::size_t len) {
38 std::string str{s, len};
39 results.push_back("'"s + str + '\'');
40 return true;
42 bool TestFormatContext::Emit(const char16_t *, std::size_t) {
43 Crash("TestFormatContext::Emit(const char16_t *) called");
44 return false;
46 bool TestFormatContext::Emit(const char32_t *, std::size_t) {
47 Crash("TestFormatContext::Emit(const char32_t *) called");
48 return false;
51 bool TestFormatContext::AdvanceRecord(int n) {
52 while (n-- > 0) {
53 results.emplace_back("/");
55 return true;
58 void TestFormatContext::HandleAbsolutePosition(std::int64_t n) {
59 results.push_back("T"s + std::to_string(n));
62 void TestFormatContext::HandleRelativePosition(std::int64_t n) {
63 if (n < 0) {
64 results.push_back("TL"s + std::to_string(-n));
65 } else {
66 results.push_back(std::to_string(n) + 'X');
70 void TestFormatContext::Report(const DataEdit &edit) {
71 std::string str{edit.descriptor};
72 if (edit.repeat != 1) {
73 str = std::to_string(edit.repeat) + '*' + str;
75 if (edit.variation) {
76 str += edit.variation;
78 if (edit.width) {
79 str += std::to_string(*edit.width);
81 if (edit.digits) {
82 str += "."s + std::to_string(*edit.digits);
84 if (edit.expoDigits) {
85 str += "E"s + std::to_string(*edit.expoDigits);
87 // modes?
88 results.push_back(str);
91 void TestFormatContext::Check(Results &expect) {
92 if (expect != results) {
93 Fail() << "expected:";
94 for (const std::string &s : expect) {
95 llvm::errs() << ' ' << s;
97 llvm::errs() << "\ngot:";
98 for (const std::string &s : results) {
99 llvm::errs() << ' ' << s;
101 llvm::errs() << '\n';
103 expect.clear();
104 results.clear();
107 static void Test(int n, const char *format, Results &&expect, int repeat = 1) {
108 TestFormatContext context;
109 FormatControl<TestFormatContext> control{
110 context, format, std::strlen(format)};
111 try {
112 for (int j{0}; j < n; ++j) {
113 context.Report(control.GetNextDataEdit(context, repeat));
115 control.Finish(context);
116 if (int iostat{context.GetIoStat()}) {
117 context.Crash("GetIoStat() == %d", iostat);
119 } catch (const std::string &crash) {
120 context.results.push_back("Crash:"s + crash);
122 context.Check(expect);
125 int main() {
126 StartTests();
127 Test(1, "('PI=',F9.7)", Results{"'PI='", "F9.7"});
128 Test(1, "(3HPI=F9.7)", Results{"'PI='", "F9.7"});
129 Test(1, "(3HPI=/F9.7)", Results{"'PI='", "/", "F9.7"});
130 Test(2, "('PI=',F9.7)", Results{"'PI='", "F9.7", "/", "'PI='", "F9.7"});
131 Test(2, "(2('PI=',F9.7),'done')",
132 Results{"'PI='", "F9.7", "'PI='", "F9.7", "'done'"});
133 Test(2, "(3('PI=',F9.7,:),'tooFar')",
134 Results{"'PI='", "F9.7", "'PI='", "F9.7"});
135 Test(2, "(*('PI=',F9.7,:),'tooFar')",
136 Results{"'PI='", "F9.7", "'PI='", "F9.7"});
137 Test(1, "(3F9.7)", Results{"2*F9.7"}, 2);
138 return EndTests();