Line data Source code
1 : /** Unit tests for Output modules of CRPropa
2 : Output
3 : TextOutput
4 : ParticleCollector
5 : */
6 :
7 : #include "CRPropa.h"
8 :
9 : #include "gtest/gtest.h"
10 : #include <iostream>
11 : #include <string>
12 :
13 :
14 : #ifdef CRPROPA_HAVE_HDF5
15 : #include <hdf5.h>
16 : #endif
17 :
18 : // compare two arrays (intead of using Google Mock)
19 : // https://stackoverflow.com/a/10062016/6819103
20 : template <typename T, size_t size>
21 1 : ::testing::AssertionResult ArraysMatch(const T (&expected)[size],
22 : const T (&actual)[size]) {
23 11 : for (size_t i(0); i < size; ++i) {
24 10 : if (expected[i] != actual[i]) {
25 : return ::testing::AssertionFailure()
26 0 : << "array[" << i << "] (" << actual[i] << ") != expected["
27 0 : << i << "] (" << expected[i] << ")";
28 : }
29 : }
30 :
31 1 : return ::testing::AssertionSuccess();
32 : }
33 :
34 : namespace crpropa {
35 :
36 : //-- Output
37 1 : TEST(Output, size) {
38 1 : Candidate c;
39 1 : Output output;
40 6 : for (int it = 0; it < 5; ++it, output.process(&c));
41 :
42 1 : EXPECT_EQ(output.size(), 5);
43 1 : }
44 :
45 : //-- TextOutput
46 1 : TEST(TextOutput, printHeader_Trajectory1D) {
47 1 : Candidate c;
48 1 : TextOutput output(Output::Trajectory1D);
49 :
50 1 : ::testing::internal::CaptureStdout();
51 1 : output.process(&c);
52 1 : std::string captured = testing::internal::GetCapturedStdout();
53 :
54 2 : EXPECT_EQ(captured.substr(0, captured.find("\n")), "#\tID\tE\tX");
55 1 : }
56 :
57 1 : TEST(TextOutput, printHeader_Event1D) {
58 1 : Candidate c;
59 1 : TextOutput output(Output::Event1D);
60 :
61 1 : ::testing::internal::CaptureStdout();
62 1 : output.process(&c);
63 1 : std::string captured = testing::internal::GetCapturedStdout();
64 :
65 2 : EXPECT_EQ(captured.substr(0, captured.find("\n")), "#\tD\tID\tE\tID0\tE0");
66 1 : }
67 :
68 1 : TEST(TextOutput, printHeader_Trajectory3D) {
69 1 : Candidate c;
70 1 : TextOutput output(Output::Trajectory3D);
71 :
72 1 : ::testing::internal::CaptureStdout();
73 1 : output.process(&c);
74 1 : std::string captured = testing::internal::GetCapturedStdout();
75 :
76 2 : EXPECT_EQ(captured.substr(0, captured.find("\n")),
77 : "#\tD\tID\tE\tX\tY\tZ\tPx\tPy\tPz");
78 1 : }
79 :
80 1 : TEST(TextOutput, printHeader_Event3D) {
81 1 : Candidate c;
82 1 : TextOutput output(Output::Event3D);
83 :
84 1 : ::testing::internal::CaptureStdout();
85 1 : output.process(&c);
86 1 : std::string captured = testing::internal::GetCapturedStdout();
87 :
88 2 : EXPECT_EQ(
89 : captured.substr(0, captured.find("\n")),
90 : "#\tD\tID\tE\tX\tY\tZ\tPx\tPy\tPz\tID0\tE0\tX0\tY0\tZ0\tP0x\tP0y\tP0z");
91 1 : }
92 :
93 1 : TEST(TextOutput, printHeader_Custom) {
94 1 : Candidate c;
95 1 : TextOutput output(Output::Event1D);
96 :
97 1 : output.enable(Output::SerialNumberColumn);
98 1 : output.disable(Output::TrajectoryLengthColumn);
99 1 : output.set(Output::RedshiftColumn, false);
100 1 : output.enable(Output::CandidateTagColumn);
101 1 : output.enable(Output::TimeColumn);
102 :
103 1 : ::testing::internal::CaptureStdout();
104 1 : output.process(&c);
105 1 : std::string captured = testing::internal::GetCapturedStdout();
106 :
107 2 : EXPECT_EQ(captured.substr(0, captured.find("\n")),
108 : "#\ttime\tSN\tID\tE\tSN0\tID0\tE0\tSN1\ttag");
109 1 : }
110 :
111 1 : TEST(TextOutput, printProperty) {
112 1 : Candidate c;
113 1 : TextOutput output(Output::Event1D);
114 1 : output.disableAll();
115 2 : output.enableProperty("foo", 2.0, "Bar");
116 :
117 1 : ::testing::internal::CaptureStdout();
118 1 : output.process(&c);
119 1 : std::string captured = testing::internal::GetCapturedStdout();
120 :
121 : // name in first line of header
122 2 : EXPECT_EQ(captured.substr(0, captured.find("\n")), "#\tfoo");
123 1 : }
124 :
125 1 : TEST(TextOutput, printHeader_Version) {
126 1 : Candidate c;
127 1 : TextOutput output(Output::Event1D);
128 :
129 1 : ::testing::internal::CaptureStdout();
130 1 : output.process(&c);
131 1 : std::string captured = testing::internal::GetCapturedStdout();
132 :
133 : // length of the prefix is 19 chars
134 1 : size_t version_pos = captured.find("# CRPropa version: ") + 19;
135 :
136 2 : EXPECT_EQ(captured.substr(version_pos,
137 : captured.find("\n", version_pos) - version_pos),
138 : g_GIT_DESC);
139 1 : }
140 :
141 : #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS
142 1 : TEST(TextOutput, failOnIllegalOutputFile) {
143 2 : EXPECT_THROW(
144 : TextOutput output("THIS_FOLDER_MUST_NOT_EXISTS_12345+/FILE.txt"),
145 : std::runtime_error);
146 1 : }
147 : #endif
148 :
149 : #ifdef CRPROPA_HAVE_HDF5
150 : #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS
151 1 : TEST(HDF5Output, failOnIllegalOutputFile) {
152 1 : HDF5Output out;
153 : // disable default error output of HDF5
154 1 : H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
155 2 : EXPECT_THROW(out.open("THIS_FOLDER_MUST_NOT_EXISTS_12345+/FILE.h5"),
156 : std::runtime_error);
157 1 : }
158 : #endif
159 : #endif
160 :
161 : //-- ParticleCollector
162 1 : TEST(ParticleCollector, size) {
163 1 : ref_ptr<Candidate> c = new Candidate();
164 1 : ParticleCollector output;
165 :
166 6 : for (int it = 0; it < 5; ++it, output.process(c))
167 : ;
168 :
169 1 : EXPECT_EQ(output.size(), 5);
170 2 : }
171 :
172 1 : TEST(ParticleCollector, fetchItem) {
173 1 : ref_ptr<Candidate> c = new Candidate(nucleusId(1, 1), 1 * EeV);
174 1 : ParticleCollector output;
175 :
176 1 : output.process(c);
177 :
178 2 : EXPECT_EQ(output[0], c);
179 2 : }
180 :
181 1 : TEST(ParticleCollector, reprocess) {
182 1 : ref_ptr<Candidate> c = new Candidate(nucleusId(1, 1), 1 * EeV);
183 1 : ParticleCollector collector;
184 1 : ParticleCollector output;
185 :
186 1 : collector.process(c);
187 1 : collector.reprocess(&output);
188 :
189 2 : EXPECT_EQ(output[0], c);
190 2 : }
191 :
192 1 : TEST(ParticleCollector, dumpload) {
193 1 : ref_ptr<Candidate> c = new Candidate(nucleusId(1, 1), 1.234 * EeV);
194 1 : c->current.setPosition(Vector3d(1, 2, 3));
195 1 : c->current.setDirection(Vector3d(-1, -1, -1));
196 1 : c->setTrajectoryLength(1 * Mpc);
197 1 : c->setRedshift(2);
198 1 : c->setTime(3 * Myr);
199 :
200 1 : ParticleCollector input;
201 1 : ParticleCollector output;
202 :
203 12 : for (int i = 0; i <= 10; ++i) {
204 22 : input.process(c);
205 : }
206 :
207 : // Well, it would be nicer if we don't need to receate any file
208 1 : input.dump("ParticleCollector_DumpTest.txt");
209 1 : output.load("ParticleCollector_DumpTest.txt");
210 :
211 1 : EXPECT_EQ(input.size(), output.size());
212 2 : EXPECT_EQ(output[0]->current.getEnergy(), c->current.getEnergy());
213 2 : EXPECT_EQ(output[1]->getTrajectoryLength(), c->getTrajectoryLength());
214 2 : EXPECT_EQ(output[2]->current.getId(), c->current.getId());
215 2 : EXPECT_EQ(output[3]->getRedshift(), c->getRedshift());
216 2 : EXPECT_EQ(output[4]->getTime(), c->getTime());
217 2 : }
218 :
219 : // Just test if the trajectory is on a line for rectilinear propagation
220 1 : TEST(ParticleCollector, getTrajectory) {
221 : int pos_x[10];
222 1 : int pos_x_expected[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
223 :
224 1 : ParticleState p;
225 1 : p.setPosition(Vector3d(10, 0, 0));
226 1 : p.setDirection(Vector3d(-1, 0, 0));
227 1 : ref_ptr<Candidate> c = new Candidate(p);
228 :
229 1 : ref_ptr<ParticleCollector> output = new ParticleCollector();
230 1 : ref_ptr<ParticleCollector> trajectory = new ParticleCollector();
231 1 : trajectory->setClone(true);
232 :
233 1 : ref_ptr<ModuleList> sim = new ModuleList();
234 1 : sim->add(new SimplePropagation(1, 1));
235 :
236 1 : ref_ptr<Observer> obs = new Observer();
237 1 : obs->add(new Observer1D());
238 1 : obs->onDetection(output);
239 1 : sim->add(obs);
240 :
241 2 : sim->run(c);
242 :
243 2 : output->getTrajectory(sim, 0, trajectory);
244 :
245 : Vector3d pos;
246 : int i = 0;
247 :
248 1 : for (ParticleCollector::iterator itr = trajectory->begin();
249 11 : itr != trajectory->end(); ++itr) {
250 10 : pos = (*(itr->get())).current.getPosition();
251 10 : pos_x[i] = pos.getX();
252 10 : ++i;
253 : }
254 :
255 1 : EXPECT_TRUE(ArraysMatch(pos_x_expected, pos_x));
256 1 : }
257 :
258 1 : TEST(ParticleCollector, runModuleList) {
259 1 : ModuleList modules;
260 1 : modules.add(new SimplePropagation());
261 1 : modules.add(new MaximumTrajectoryLength(1 * Mpc));
262 :
263 1 : ParticleState p;
264 1 : p.setPosition(Vector3d(10, 0, 0));
265 1 : p.setDirection(Vector3d(-1, 0, 0));
266 1 : ref_ptr<Candidate> c = new Candidate(p);
267 :
268 1 : ref_ptr<ParticleCollector> collector = new ParticleCollector();
269 :
270 1 : collector->process(c);
271 :
272 1 : modules.setShowProgress(false);
273 1 : auto candidates = collector->getContainer();
274 1 : modules.run(&candidates);
275 2 : }
276 :
277 0 : int main(int argc, char **argv) {
278 0 : ::testing::InitGoogleTest(&argc, argv);
279 0 : return RUN_ALL_TESTS();
280 : }
281 :
282 : } // namespace crpropa
|