IODA
ObsSpaceInvalidNumeric.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2018-2021 UCAR
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  */
7 
8 #ifndef TEST_IODA_OBSSPACEINVALIDNUMERIC_H_
9 #define TEST_IODA_OBSSPACEINVALIDNUMERIC_H_
10 
11 #include <cmath>
12 #include <string>
13 #include <vector>
14 
15 #define ECKIT_TESTING_SELF_REGISTER_CASES 0
16 
17 #include <boost/noncopyable.hpp>
18 #include <boost/shared_ptr.hpp>
19 
20 #include "eckit/config/LocalConfiguration.h"
21 #include "eckit/testing/Test.h"
22 
23 #include "oops/mpi/mpi.h"
24 #include "oops/runs/Test.h"
25 #include "oops/test/TestEnvironment.h"
26 
27 #include "ioda/IodaTrait.h"
28 #include "ioda/ObsSpace.h"
29 
30 namespace ioda {
31 namespace test {
32 
33 // -----------------------------------------------------------------------------
34 
35 class ObsSpaceTestFixture : private boost::noncopyable {
36  public:
37  static ioda::ObsSpace & obspace(const std::size_t ii) {
38  return *getInstance().ospaces_.at(ii);
39  }
40  static std::size_t size() {return getInstance().ospaces_.size();}
41  static void cleanup() {
42  auto &spaces = getInstance().ospaces_;
43  for (auto &space : spaces) {
44  space->save();
45  space.reset();
46  }
47  }
48 
49  private:
51  static ObsSpaceTestFixture theObsSpaceTestFixture;
52  return theObsSpaceTestFixture;
53  }
54 
56  util::DateTime bgn(::test::TestEnvironment::config().getString("window begin"));
57  util::DateTime end(::test::TestEnvironment::config().getString("window end"));
58 
59  std::vector<eckit::LocalConfiguration> conf;
60  ::test::TestEnvironment::config().get("observations", conf);
61 
62  for (std::size_t jj = 0; jj < conf.size(); ++jj) {
63  eckit::LocalConfiguration obsconf(conf[jj], "obs space");
64  std::string distname = obsconf.getString("distribution", "RoundRobin");
65  boost::shared_ptr<ioda::ObsSpace> tmp(new ioda::ObsSpace(obsconf, oops::mpi::world(),
66  bgn, end, oops::mpi::myself()));
67  ospaces_.push_back(tmp);
68  }
69  }
70 
72 
73  std::vector<boost::shared_ptr<ioda::ObsSpace> > ospaces_;
74 };
75 
76 // -----------------------------------------------------------------------------
77 
79  typedef ObsSpaceTestFixture Test_;
80 
81  std::vector<eckit::LocalConfiguration> conf;
82  ::test::TestEnvironment::config().get("observations", conf);
83 
84  for (std::size_t jj = 0; jj < Test_::size(); ++jj) {
85  // Grab the obs space and test data configurations
86  eckit::LocalConfiguration obsConfig;
87  eckit::LocalConfiguration testConfig;
88  conf[jj].get("obs space", obsConfig);
89  conf[jj].get("test data", testConfig);
90 
91  const ObsSpace &odb = Test_::obspace(jj);
92 
93  // Get the list of variables to check from the test configuration
94  std::vector<eckit::LocalConfiguration> testConfigVars;
95  testConfig.get("variables", testConfigVars);
96  float testTol = testConfig.getFloat("tolerance");
97 
98  // Check that that invalid numeric values got handled properly
99  for (std::size_t i = 0; i < testConfigVars.size(); ++i) {
100  std::string varName = testConfigVars[i].getString("name");
101  std::string groupName = testConfigVars[i].getString("group");
102  std::string varType = testConfigVars[i].getString("type");
103 
104  if (varType == "int") {
105  std::vector<int> expectedTestVals = testConfigVars[i].getIntVector("values");
106  std::vector<int> testVals;
107  odb.get_db(groupName, varName, testVals);
108  EXPECT_EQUAL(testVals, expectedTestVals);
109  } else if (varType == "float") {
110  std::vector<float> expectedTestVals = testConfigVars[i].getFloatVector("values");
111  std::vector<float> testVals;
112  odb.get_db(groupName, varName, testVals);
113  for (std::size_t j = 0; j < expectedTestVals.size(); ++j) {
114  EXPECT(oops::is_close(testVals[j], expectedTestVals[j], testTol));
115  }
116  } else if (varType == "string") {
117  std::vector<std::string> expectedTestVals =
118  testConfigVars[i].getStringVector("values");
119  std::vector<std::string> testVals;
120  odb.get_db(groupName, varName, testVals);
121  EXPECT_EQUAL(testVals, expectedTestVals);
122  }
123  }
124  }
125 }
126 
127 // -----------------------------------------------------------------------------
128 
129 void testCleanup() {
130  // This test removes the obsspaces and ensures that they evict their contents
131  // to disk successfully.
132  typedef ObsSpaceTestFixture Test_;
133 
134  Test_::cleanup();
135 }
136 
137 // -----------------------------------------------------------------------------
138 
139 class ObsSpaceInvalidNumeric : public oops::Test {
140  public:
143 
144  private:
145  std::string testid() const override {return "test::ObsSpaceInvalidNumeric<ioda::IodaTrait>";}
146 
147  void register_tests() const override {
148  std::vector<eckit::testing::Test>& ts = eckit::testing::specification();
149 
150  ts.emplace_back(CASE("ioda/ObsSpace/testInvalidNumeric")
151  { testInvalidNumeric(); });
152  ts.emplace_back(CASE("ioda/ObsSpace/testCleanup")
153  { testCleanup(); });
154  }
155 
156  void clear() const override {}
157 };
158 
159 // -----------------------------------------------------------------------------
160 
161 } // namespace test
162 } // namespace ioda
163 
164 #endif // TEST_IODA_OBSSPACEINVALIDNUMERIC_H_
Observation data class for IODA.
Definition: src/ObsSpace.h:116
std::string testid() const override
std::vector< boost::shared_ptr< ioda::ObsSpace > > ospaces_
static ioda::ObsSpace & obspace(const std::size_t ii)
static ObsSpaceTestFixture & getInstance()
CASE("Derived variable and unit conversion methods")