Macros | Functions
ParameterSetRegistry_t.cc File Reference
#include "boost/test/unit_test.hpp"
#include "cetlib/container_algorithms.h"
#include "fhiclcpp/ParameterSetRegistry.h"
#include "fhiclcpp/test/boost_test_print_pset.h"
#include "hep_concurrency/simultaneous_function_spawner.h"
#include "sqlite3.h"
#include <atomic>
#include <functional>
#include <mutex>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

Go to the source code of this file.

Macros

#define BOOST_TEST_MODULE   (ParameterSetRegistry_t)
 

Functions

 BOOST_AUTO_TEST_CASE (Typedefs)
 
 BOOST_AUTO_TEST_CASE (MakeAndAdd)
 
 BOOST_AUTO_TEST_CASE (AddFromIterAndGet)
 
 BOOST_AUTO_TEST_CASE (TestImport)
 
 BOOST_AUTO_TEST_CASE (TestExport)
 

Macro Definition Documentation

#define BOOST_TEST_MODULE   (ParameterSetRegistry_t)

Definition at line 2 of file ParameterSetRegistry_t.cc.

Function Documentation

BOOST_AUTO_TEST_CASE ( Typedefs  )

Definition at line 29 of file ParameterSetRegistry_t.cc.

30 {
31  using ctype =
32  unordered_map<ParameterSetID, ParameterSet, detail::HashParameterSetID>;
33  static_assert(is_same_v<ctype, ParameterSetRegistry::collection_type>);
34  static_assert(is_same_v<ParameterSetID, ParameterSetRegistry::key_type>);
35  static_assert(is_same_v<ParameterSet, ParameterSetRegistry::mapped_type>);
36  static_assert(is_same_v<pair<ParameterSetID const, ParameterSet>,
38  static_assert(is_same_v<size_t, ParameterSetRegistry::size_type>);
39  static_assert(
40  is_same_v<ctype::const_iterator, ParameterSetRegistry::const_iterator>);
41 }
typename collection_type::value_type value_type
BOOST_AUTO_TEST_CASE ( MakeAndAdd  )

Definition at line 43 of file ParameterSetRegistry_t.cc.

44 {
47  auto const pset = ParameterSet::make(
48  "x: 5 y: { a: \"oops\" b: 9 } z: { c: \"Looooong striiiiiing.\" }");
51  ParameterSetRegistry::put(pset);
53  auto ps2 = ParameterSetRegistry::get(pset.id());
54  BOOST_TEST_REQUIRE(pset.id() == ps2.id());
55  BOOST_TEST_REQUIRE(pset == ps2);
56 }
BOOST_TEST_REQUIRE(static_cast< bool >(inFile))
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
unique_ptr< InputSource > make(ParameterSet const &conf, InputSourceDescription &desc)
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
Definition: StdUtils.h:97
BOOST_AUTO_TEST_CASE ( AddFromIterAndGet  )

Definition at line 58 of file ParameterSetRegistry_t.cc.

59 {
60  vector<ParameterSet> v1;
61  auto expected_size = ParameterSetRegistry::size() + 2ul; // a3, x.
62  for (auto s :
63  {"a1: 4 b1: 7.0 c1: [ 5, 4, 3 ]",
64  "a2: [ oh, my, stars ]",
65  "a3: { x: { y: [ now, is, the, time, for, all, good, men ] } }"}) {
66  v1.push_back(ParameterSet::make(s));
67  }
69  vector<ParameterSetRegistry::value_type> v2;
70  string const f{"filler"};
71  for (auto p : v1) {
72  p.put("f", f);
73  v2.emplace_back(p.id(), move(p));
74  }
75  expected_size += 3;
76  ParameterSetRegistry::put(v1.cbegin(), v1.cend());
78  expected_size += 3;
79  ParameterSetRegistry::put(v2.cbegin(), v2.cend());
81  ParameterSet pset;
82  ParameterSetRegistry::get(v2.front().first, pset);
83  BOOST_TEST_REQUIRE(pset == v2.front().second);
84  auto p2 = ParameterSetRegistry::get(v2.back().first);
85  BOOST_TEST_REQUIRE(p2 == v2.back().second);
86 }
BOOST_TEST_REQUIRE(static_cast< bool >(inFile))
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
def move(depos, offset)
Definition: depos.py:107
p
Definition: test.py:223
unique_ptr< InputSource > make(ParameterSet const &conf, InputSourceDescription &desc)
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
static QCString * s
Definition: config.cpp:1042
BOOST_AUTO_TEST_CASE ( TestImport  )

Definition at line 88 of file ParameterSetRegistry_t.cc.

89 {
90  atomic<size_t> expected_size{ParameterSetRegistry::size()};
91  sqlite3* db = nullptr;
92  BOOST_TEST_REQUIRE(!sqlite3_open(":memory:", &db));
94  char* errMsg = nullptr;
95  sqlite3_exec(db,
96  "BEGIN TRANSACTION; DROP TABLE IF EXISTS ParameterSets;"
97  "CREATE TABLE ParameterSets(ID PRIMARY KEY, PSetBlob); COMMIT;",
98  nullptr,
99  nullptr,
100  &errMsg);
101  throwOnSQLiteFailure(db, errMsg);
102  // testData: bool represents whether the top-level set is already
103  // expected to be in the registry or not.
104  vector<pair<string, bool>> testData{
105  {"x: [ 1, 3, 5, 7 ]", false},
106  {"a2: [ oh, my, stars ]", true}, // Should match a2, above.
107  {"y1: \"Oh, home on the range\" y2: \"Where the deer and the antelope "
108  "roam\"",
109  false}};
110  vector<pair<ParameterSet, bool>> v1(testData.size());
111  // Make ParameterSets in parallel
112  {
113  vector<function<void()>> tasks;
114  cet::for_all_with_index(testData,
115  [&v1, &tasks](size_t const i, auto const& p) {
116  auto& entry = v1[i];
117  tasks.push_back([&entry, &p] {
118  auto pset = ParameterSet::make(p.first);
119  entry = make_pair(pset, p.second);
120  });
121  });
122  simultaneous_function_spawner sfs{tasks};
123  }
124  // Insert ParameterSets into db in parallel
125  {
126  std::recursive_mutex m{};
127  auto insert_into_db = [&db, &m](auto const& pr) {
128  // Since this lambda is intended to be executed in parallel, one
129  // should not specify a BEGIN (IMMEDIATE|EXCLUSIVE) TRANSACTION
130  // statement--when executed in parallel, two or more BEGIN
131  // statements could be executed in succession, which is an
132  // error. Rather, one should rely on the SQLite's internal
133  // locking mechanisms to ensure an appropriate transaction.
134  // Note that SQLite implicitly assumes a transaction is in
135  // flight until an sqlite3_reset or sqlite3_finalize function
136  // call is made, at which point it is committed.
137  sqlite3_stmt* oStmt = nullptr;
138  sqlite3_prepare_v2(
139  db,
140  "INSERT INTO ParameterSets(ID, PSetBlob) VALUES(?, ?);",
141  -1,
142  &oStmt,
143  nullptr);
145  auto const& pset = pr.first;
146  bool const inRegistry{pr.second};
147  string const id{pset.id().to_string()};
148  auto const rc1 =
149  sqlite3_bind_text(oStmt, 1, id.c_str(), id.size() + 1, SQLITE_STATIC);
151 
152  string const psBlob{pset.to_compact_string()};
153  auto const rc2 = sqlite3_bind_text(
154  oStmt, 2, psBlob.c_str(), psBlob.size() + 1, SQLITE_STATIC);
156  {
157  // FIXME: sqlite3_step is not thread-safe according to tsan!
158  std::lock_guard sentry{m};
159  assert(sqlite3_step(oStmt) == SQLITE_DONE);
160  }
161  auto const rc3 = sqlite3_finalize(oStmt);
163 
164  assert(ParameterSetRegistry::has(pset.id()) == inRegistry);
165  };
166  vector<function<void()>> tasks;
168  v1, back_inserter(tasks), [insert_into_db](auto const& pr) {
169  return [insert_into_db, pr] { insert_into_db(pr); };
170  });
171  simultaneous_function_spawner sfs{tasks};
172  }
174  ParameterSetRegistry::importFrom(db);
175  // Make sure the registry didn't expand as a result of the insert.
177  BOOST_TEST_REQUIRE(sqlite3_close(db) == SQLITE_OK);
178  // Read from registry in parallel
179  {
180  std::recursive_mutex m{};
181  auto read_from_registry = [&expected_size, &m](auto const& p) {
182  auto const& id = p.first.id();
183  if (p.second) {
184  {
185  // FIXME: Not thread-safe according to tsan!
186  std::lock_guard sentry{m};
187  // Should be in registry already.
188  BOOST_TEST_REQUIRE(ParameterSetRegistry::has(id));
189  }
190  } else {
191  {
192  // FIXME: Not thread-safe according to tsan!
193  std::lock_guard sentry{m};
194  // Make sure the import didn't inject them into the registry.
195  BOOST_TEST_REQUIRE(!ParameterSetRegistry::has(id));
196  }
197  // We expect the get() call below to increase the size of the
198  // registry by pulling the entry in from the backing DB.
199  ++expected_size;
200  }
201  {
202  // FIXME: Not thread-safe according to tsan!
203  std::lock_guard sentry{m};
204  auto const& p2 = ParameterSetRegistry::get(id);
205  BOOST_TEST_REQUIRE(p2 == p.first);
206  }
207  };
208  vector<function<void()>> tasks;
210  v1, back_inserter(tasks), [read_from_registry](auto const& p) {
211  return [read_from_registry, p] { read_from_registry(p); };
212  });
213  simultaneous_function_spawner sfs{tasks};
215  }
216 }
QList< Entry > entry
void for_all_with_index(FwdCont &, Func)
struct sqlite3_stmt sqlite3_stmt
BOOST_TEST_REQUIRE(static_cast< bool >(inFile))
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
p
Definition: test.py:223
auto transform_all(Container &, OutputIt, UnaryOp)
struct sqlite3 sqlite3
unique_ptr< InputSource > make(ParameterSet const &conf, InputSourceDescription &desc)
void throwOnSQLiteFailure(int rc, char *msg=nullptr)
auto const & get(AssnsNode< L, R, D > const &r)
Definition: AssnsNode.h:115
BOOST_AUTO_TEST_CASE ( TestExport  )

Definition at line 218 of file ParameterSetRegistry_t.cc.

219 {
220  sqlite3* db = nullptr;
221  BOOST_TEST_REQUIRE(!sqlite3_open(":memory:", &db));
222  // Check empty!
223  sqlite3_stmt* stmt = nullptr;
224  // Make sure we get our own fresh and empty DB.
225  sqlite3_prepare_v2(
226  db,
227  "SELECT 1 from sqlite_master where type='table' and name='ParameterSets';",
228  -1,
229  &stmt,
230  nullptr);
231  BOOST_TEST_REQUIRE(sqlite3_step(stmt) == SQLITE_DONE); // No rows.
232  sqlite3_reset(stmt);
233  ParameterSetRegistry::exportTo(db);
234  BOOST_TEST_REQUIRE(sqlite3_step(stmt) == SQLITE_ROW); // Found table.
235  sqlite3_finalize(stmt);
236  sqlite3_prepare_v2(
237  db, "SELECT COUNT(*) from ParameterSets;", -1, &stmt, nullptr);
238  BOOST_TEST_REQUIRE(sqlite3_step(stmt) == SQLITE_ROW);
239  BOOST_TEST_REQUIRE(sqlite3_column_int64(stmt, 0) == 13l);
240  sqlite3_finalize(stmt);
241  sqlite3_close(db);
242 }
struct sqlite3_stmt sqlite3_stmt
BOOST_TEST_REQUIRE(static_cast< bool >(inFile))
static QStrList * l
Definition: config.cpp:1044
struct sqlite3 sqlite3