1 #include <adios2.h>
2 #include <array>
3 #include <condition_variable>
4 #include <future>
5 #include <iostream>
6 #include <numeric>
7 #include <thread>
8
9 #include <gtest/gtest.h>
10
11 #include "ParseArgs.h"
12
13 using dt = long long;
14
15 int value_errors = 0;
16
17 std::mutex StdOutMtx;
18
Read(int ID)19 int Read(int ID)
20 {
21 adios2::ADIOS adios;
22 adios2::IO io = adios.DeclareIO("IO");
23
24 {
25 std::lock_guard<std::mutex> guard(StdOutMtx);
26 std::cout << "Reader: engine = " << engine << std::endl;
27 }
28 io.SetEngine(engine);
29 io.SetParameters(engineParams);
30
31 {
32 std::lock_guard<std::mutex> guard(StdOutMtx);
33 std::cout << "Reader: call Open" << std::endl;
34 }
35
36 try
37 {
38 std::string FName = "File" + std::to_string(ID);
39 adios2::Engine Reader = io.Open(FName, adios2::Mode::Read);
40 {
41 std::lock_guard<std::mutex> guard(StdOutMtx);
42 std::cout << "Reader: passed Open" << std::endl;
43 }
44 std::array<dt, 1000> ar;
45
46 auto status = Reader.BeginStep();
47 {
48 std::lock_guard<std::mutex> guard(StdOutMtx);
49 std::cout << "Reader: passed BeginStep";
50 }
51 if (status == adios2::StepStatus::EndOfStream)
52 {
53 {
54 std::lock_guard<std::mutex> guard(StdOutMtx);
55 std::cout << " with EndOfStream " << std::endl;
56 }
57 return false;
58 }
59 {
60 std::lock_guard<std::mutex> guard(StdOutMtx);
61 std::cout << " with success " << std::endl;
62 }
63
64 adios2::Variable<dt> var = io.InquireVariable<dt>("data");
65 Reader.Get(var, ar.begin());
66 Reader.EndStep();
67 dt expect = 0;
68 for (auto &val : ar)
69 {
70 if (val != expect)
71 {
72 value_errors++;
73 }
74 expect++;
75 }
76
77 Reader.Close();
78 {
79 std::lock_guard<std::mutex> guard(StdOutMtx);
80 std::cout << "Reader got " << expect << " values, " << value_errors
81 << " were incorrect" << std::endl;
82 }
83 }
84 catch (std::exception &e)
85 {
86 {
87 std::lock_guard<std::mutex> guard(StdOutMtx);
88 std::cout << "Reader: Exception: " << e.what() << std::endl;
89 }
90 return false;
91 }
92 return true;
93 }
94
Write(int ID)95 bool Write(int ID)
96 {
97 adios2::ADIOS adios;
98 adios2::IO io = adios.DeclareIO("IO");
99 io.SetEngine(engine);
100 io.SetParameters(engineParams);
101 {
102 std::lock_guard<std::mutex> guard(StdOutMtx);
103 std::cout << "Writer: engine = " << engine << std::endl;
104 }
105 auto var = io.DefineVariable<dt>("data", adios2::Dims{100, 10},
106 adios2::Dims{0, 0}, adios2::Dims{100, 10});
107
108 std::array<dt, 1000> ar;
109 std::iota(ar.begin(), ar.end(), 0);
110
111 try
112 {
113 std::string FName = "File" + std::to_string(ID);
114 adios2::Engine Writer = io.Open(FName, adios2::Mode::Write);
115
116 {
117 std::lock_guard<std::mutex> guard(StdOutMtx);
118 std::cout << "Writer completed Open() " << std::endl;
119 }
120 Writer.BeginStep();
121 Writer.Put<dt>(var, ar.begin());
122 Writer.EndStep();
123 Writer.Close();
124 {
125 std::lock_guard<std::mutex> guard(StdOutMtx);
126 std::cout << "Writer completed Close() " << std::endl;
127 }
128 }
129 catch (std::exception &e)
130 {
131 {
132 std::lock_guard<std::mutex> guard(StdOutMtx);
133 std::cout << "Writer: Exception: " << e.what() << std::endl;
134 }
135 return false;
136 }
137 return true;
138 }
139
140 class TestThreads : public ::testing::Test
141 {
142 public:
143 TestThreads() = default;
144 };
145
TEST_F(TestThreads,Basic)146 TEST_F(TestThreads, Basic)
147 {
148 auto read_fut = std::async(std::launch::async, Read, 0);
149 auto write_fut = std::async(std::launch::async, Write, 0);
150 bool reader_success = read_fut.get();
151 bool writer_success = write_fut.get();
152 EXPECT_TRUE(reader_success);
153 EXPECT_TRUE(writer_success);
154 EXPECT_EQ(value_errors, 0)
155 << "We got " << value_errors << " erroneous values at the reader";
156 }
157
158 // This test tries to push up to the limits to see if we're leaking FDs, but it
159 // runs slowly, commenting it out until needed.
160 //
161 // TEST_F(TestThreads, Repeated)
162 // {
163 // auto high_write_fut = std::async(std::launch::async, Write, 0);
164 // for (int i = 0; i < 1024; i++)
165 // {
166 // auto read_fut = std::async(std::launch::async, Read, i + 1);
167 // auto write_fut = std::async(std::launch::async, Write, i + 1);
168 // bool reader_success = read_fut.get();
169 // bool writer_success = write_fut.get();
170 // EXPECT_TRUE(reader_success);
171 // EXPECT_TRUE(writer_success);
172 // EXPECT_EQ(value_errors, 0)
173 // << "We got " << value_errors << " erroneous values at the
174 // reader";
175 // std::cout << "finished pair " << i << std::endl;
176 // }
177 // auto high_read_fut = std::async(std::launch::async, Read, 0);
178 // bool reader_success = high_read_fut.get();
179 // bool writer_success = high_write_fut.get();
180 // EXPECT_TRUE(reader_success);
181 // EXPECT_TRUE(writer_success);
182 // EXPECT_EQ(value_errors, 0);
183 // }
184
main(int argc,char ** argv)185 int main(int argc, char **argv)
186 {
187 ::testing::InitGoogleTest(&argc, argv);
188 ParseArgs(argc, argv);
189
190 int result;
191 result = RUN_ALL_TESTS();
192 return result;
193 }
194