LCOV - code coverage report
Current view: top level - test - testOutput.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 157 162 96.9 %
Date: 2024-04-29 14:43:01 Functions: 17 18 94.4 %

          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             : 
     102           1 :         ::testing::internal::CaptureStdout();
     103           1 :         output.process(&c);
     104           1 :         std::string captured = testing::internal::GetCapturedStdout();
     105             : 
     106           2 :         EXPECT_EQ(captured.substr(0, captured.find("\n")),
     107             :                   "#\tSN\tID\tE\tSN0\tID0\tE0\tSN1\ttag");
     108           1 : }
     109             : 
     110           1 : TEST(TextOutput, printProperty) {
     111           1 :         Candidate c;
     112           1 :         TextOutput output(Output::Event1D);
     113           1 :         output.disableAll();
     114           2 :         output.enableProperty("foo", 2.0, "Bar");
     115             : 
     116           1 :         ::testing::internal::CaptureStdout();
     117           1 :         output.process(&c);
     118           1 :         std::string captured = testing::internal::GetCapturedStdout();
     119             : 
     120             :         // name in first line of header
     121           2 :         EXPECT_EQ(captured.substr(0, captured.find("\n")), "#\tfoo");
     122           1 : }
     123             : 
     124           1 : TEST(TextOutput, printHeader_Version) {
     125           1 :         Candidate c;
     126           1 :         TextOutput output(Output::Event1D);
     127             : 
     128           1 :         ::testing::internal::CaptureStdout();
     129           1 :         output.process(&c);
     130           1 :         std::string captured = testing::internal::GetCapturedStdout();
     131             : 
     132             :         // length of the prefix is 19 chars
     133           1 :         size_t version_pos = captured.find("# CRPropa version: ") + 19;
     134             : 
     135           2 :         EXPECT_EQ(captured.substr(version_pos,
     136             :                                   captured.find("\n", version_pos) - version_pos),
     137             :                   g_GIT_DESC);
     138           1 : }
     139             : 
     140             : #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS
     141           1 : TEST(TextOutput, failOnIllegalOutputFile) {
     142           2 :         EXPECT_THROW(
     143             :             TextOutput output("THIS_FOLDER_MUST_NOT_EXISTS_12345+/FILE.txt"),
     144             :             std::runtime_error);
     145           1 : }
     146             : #endif
     147             : 
     148             : #ifdef CRPROPA_HAVE_HDF5
     149             : #ifndef CRPROPA_TESTS_SKIP_EXCEPTIONS
     150           1 : TEST(HDF5Output, failOnIllegalOutputFile) {
     151           1 :         HDF5Output out;
     152             :         // disable default error output of HDF5
     153           1 :         H5Eset_auto2(H5E_DEFAULT, NULL, NULL);
     154           2 :         EXPECT_THROW(out.open("THIS_FOLDER_MUST_NOT_EXISTS_12345+/FILE.h5"),
     155             :                      std::runtime_error);
     156           1 : }
     157             : #endif
     158             : #endif
     159             : 
     160             : //-- ParticleCollector
     161           2 : TEST(ParticleCollector, size) {
     162           2 :         ref_ptr<Candidate> c = new Candidate();
     163           1 :         ParticleCollector output;
     164             : 
     165           6 :         for (int it = 0; it < 5; ++it, output.process(c))
     166             :                 ;
     167             : 
     168           1 :         EXPECT_EQ(output.size(), 5);
     169           2 : }
     170             : 
     171           1 : TEST(ParticleCollector, fetchItem) {
     172           2 :         ref_ptr<Candidate> c = new Candidate(nucleusId(1, 1), 1 * EeV);
     173           1 :         ParticleCollector output;
     174             : 
     175           1 :         output.process(c);
     176             : 
     177           2 :         EXPECT_EQ(output[0], c);
     178           2 : }
     179             : 
     180           1 : TEST(ParticleCollector, reprocess) {
     181           2 :         ref_ptr<Candidate> c = new Candidate(nucleusId(1, 1), 1 * EeV);
     182           1 :         ParticleCollector collector;
     183           1 :         ParticleCollector output;
     184             : 
     185           1 :         collector.process(c);
     186           1 :         collector.reprocess(&output);
     187             : 
     188           2 :         EXPECT_EQ(output[0], c);
     189           2 : }
     190             : 
     191           1 : TEST(ParticleCollector, dumpload) {
     192           2 :         ref_ptr<Candidate> c = new Candidate(nucleusId(1, 1), 1.234 * EeV);
     193           1 :         c->current.setPosition(Vector3d(1, 2, 3));
     194           1 :         c->current.setDirection(Vector3d(-1, -1, -1));
     195           1 :         c->setTrajectoryLength(1 * Mpc);
     196           1 :         c->setRedshift(2);
     197             : 
     198           1 :         ParticleCollector input;
     199           1 :         ParticleCollector output;
     200             : 
     201          12 :         for (int i = 0; i <= 10; ++i) {
     202          22 :                 input.process(c);
     203             :         }
     204             : 
     205             :         // Well, it would be nicer if we don't need to receate any file
     206           1 :         input.dump("ParticleCollector_DumpTest.txt");
     207           1 :         output.load("ParticleCollector_DumpTest.txt");
     208             : 
     209           1 :         EXPECT_EQ(input.size(), output.size());
     210           2 :         EXPECT_EQ(output[0]->current.getEnergy(), c->current.getEnergy());
     211           2 :         EXPECT_EQ(output[1]->getTrajectoryLength(), c->getTrajectoryLength());
     212           2 :         EXPECT_EQ(output[2]->current.getId(), c->current.getId());
     213           2 :         EXPECT_EQ(output[3]->getRedshift(), c->getRedshift());
     214           2 : }
     215             : 
     216             : // Just test if the trajectory is on a line for rectilinear propagation
     217           1 : TEST(ParticleCollector, getTrajectory) {
     218             :         int pos_x[10];
     219           1 :         int pos_x_expected[] = {9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
     220             : 
     221           1 :         ParticleState p;
     222           1 :         p.setPosition(Vector3d(10, 0, 0));
     223           1 :         p.setDirection(Vector3d(-1, 0, 0));
     224           1 :         ref_ptr<Candidate> c = new Candidate(p);
     225             : 
     226           1 :         ref_ptr<ParticleCollector> output = new ParticleCollector();
     227           1 :         ref_ptr<ParticleCollector> trajectory = new ParticleCollector();
     228           1 :         trajectory->setClone(true);
     229             : 
     230           1 :         ref_ptr<ModuleList> sim = new ModuleList();
     231           1 :         sim->add(new SimplePropagation(1, 1));
     232             : 
     233           1 :         ref_ptr<Observer> obs = new Observer();
     234           1 :         obs->add(new Observer1D());
     235           1 :         obs->onDetection(output);
     236           1 :         sim->add(obs);
     237             : 
     238           2 :         sim->run(c);
     239             : 
     240           2 :         output->getTrajectory(sim, 0, trajectory);
     241             : 
     242             :         Vector3d pos;
     243             :         int i = 0;
     244             : 
     245           1 :         for (ParticleCollector::iterator itr = trajectory->begin();
     246          11 :              itr != trajectory->end(); ++itr) {
     247          10 :                 pos = (*(itr->get())).current.getPosition();
     248          10 :                 pos_x[i] = pos.getX();
     249          10 :                 ++i;
     250             :         }
     251             : 
     252           1 :         EXPECT_TRUE(ArraysMatch(pos_x_expected, pos_x));
     253           1 : }
     254             : 
     255           1 : TEST(ParticleCollector, runModuleList) {
     256           1 :         ModuleList modules;
     257           2 :         modules.add(new SimplePropagation());
     258           1 :         modules.add(new MaximumTrajectoryLength(1 * Mpc));
     259             : 
     260           1 :         ParticleState p;
     261           1 :         p.setPosition(Vector3d(10, 0, 0));
     262           1 :         p.setDirection(Vector3d(-1, 0, 0));
     263           1 :         ref_ptr<Candidate> c = new Candidate(p);
     264             : 
     265           1 :         ref_ptr<ParticleCollector> collector = new ParticleCollector();
     266             : 
     267           1 :         collector->process(c);
     268             : 
     269           1 :         modules.setShowProgress(false);
     270           1 :         auto candidates = collector->getContainer();
     271           1 :         modules.run(&candidates);
     272           2 : }
     273             : 
     274           0 : int main(int argc, char **argv) {
     275           0 :         ::testing::InitGoogleTest(&argc, argv);
     276           0 :         return RUN_ALL_TESTS();
     277             : }
     278             : 
     279             : } // namespace crpropa

Generated by: LCOV version 1.14