carl  24.04
Computer ARithmetic Library
CheckpointVerifier.h
Go to the documentation of this file.
1 #pragma once
2 
8 
9 #include <any>
10 
11 #include <queue>
12 #include <tuple>
13 #include <typeinfo>
14 #include <type_traits>
15 #include <utility>
16 
17 namespace carl {
18 namespace checkpoints {
20  template<typename... Args>
21  using Tuple = std::tuple<std::decay_t<Args>...>;
22  using Checkpoint = std::tuple<std::string,bool,std::any>;
23  private:
24  std::vector<Checkpoint> mData;
25  std::size_t mCurrent = 0;
26 
27  const Checkpoint& cur() const {
28  assert(valid());
29  return mData[mCurrent];
30  }
31  public:
34  }
35  const std::string& description() const {
36  return std::get<0>(cur());
37  }
38  bool forced() const {
39  return std::get<1>(cur());
40  }
41  template<typename T>
42  const T& data() const {
43  return std::any_cast<T>(std::get<2>(cur()));
44  }
45  template<typename T>
46  const T* try_data() const {
47  return std::any_cast<T>(&std::get<2>(cur()));
48  }
49  bool valid() const {
50  return mData.size() > mCurrent;
51  }
52  void next() {
53  mCurrent++;
54  }
55 
56  template<typename... Args>
57  void add(const std::string& description, bool forced, Args&&... args) {
58  mData.emplace_back(description, forced, std::any(Tuple<Args...>(args...)));
59  }
60  void clear() {
61  mData.clear();
62  mCurrent = 0;
63  }
64 
65  bool mayExceed = true;
66  bool printDebug = true;
67  };
68 
69  class CheckpointVerifier : public carl::Singleton<CheckpointVerifier> {
70  template<typename... Args>
71  using Tuple = CheckpointVector::Tuple<Args...>;
72  using Channels = std::map<std::string, CheckpointVector>;
73  private:
75  public:
79  }
80  template<typename... Args>
81  void push(const std::string& channel, const std::string& description, bool forced, Args&&... args) {
82  mChannels[channel].add(description, forced, std::forward<Args>(args)...);
83  CARL_LOG_DEBUG("carl.checkpoint", "Added " << (forced ? "forced " : "") << description << ": " << Tuple<Args...>(args...) << " in " << channel);
84  CARL_LOG_DEBUG("carl.checkpoint", "Type: " << carl::demangle(typeid(Tuple<Args...>).name()));
85  }
86  template<typename... Args>
87  bool check(const std::string& channel, const std::string& description, Args&&... args) {
88 
89  if (!mChannels[channel].valid()) {
90  CARL_LOG_WARN("carl.checkpoint", "No Checkpoints left in " << channel << ", got " << Tuple<Args...>(args...));
91  return mChannels[channel].mayExceed;
92  }
93  if (mChannels[channel].description() != description) {
94  CARL_LOG_ERROR("carl.checkpoint", "Expected " << mChannels[channel].description() << " but got " << description << " in " << channel);
95  return !mChannels[channel].forced();
96  }
97  const Tuple<Args...>* checkpoint = mChannels[channel].try_data<Tuple<Args...>>();
98  if (checkpoint == nullptr) {
99  CARL_LOG_ERROR("carl.checkpoint", "Got " << description << " with offending data type: " << Tuple<Args...>(args...));
100  CARL_LOG_ERROR("carl.checkpoint", "Offending type: " << carl::demangle(typeid(Tuple<Args...>).name()));
101  return !mChannels[channel].forced();
102  }
103  bool res = *checkpoint == Tuple<Args...>(args...);
104  if (!res) {
105  CARL_LOG_ERROR("carl.checkpoint", "Expected " << *checkpoint << " -> " << std::boolalpha << res);
106  CARL_LOG_ERROR("carl.checkpoint", "Expectation failed, got " << Tuple<Args...>(args...));
107  } else if (mChannels[channel].printDebug) {
108  CARL_LOG_ERROR("carl.checkpoint", "Expected " << *checkpoint << " -> " << std::boolalpha << res);
109  }
110  res = !mChannels[channel].forced() || res;
111  mChannels[channel].next();
112  return res;
113  }
114  template<typename... Args>
115  void expect(const std::string& channel, const std::string& description, Args&&... args) {
116  if (mChannels[channel].printDebug) {
117  CARL_LOG_ERROR("carl.checkpoint", "*****");
118  CARL_LOG_ERROR("carl.checkpoint", "***** Checkpoint for " << channel);
119  CARL_LOG_ERROR("carl.checkpoint", "***** Data provided: " << description << " " << Tuple<Args...>(args...));
120  CARL_LOG_ERROR("carl.checkpoint", "*****");
121  }
122  auto res = check(channel, description, args...);
123  if (mChannels[channel].printDebug) {
124  CARL_LOG_ERROR("carl.checkpoint", "*****");
125  CARL_LOG_ERROR("carl.checkpoint", "*****");
126  CARL_LOG_ERROR("carl.checkpoint", "*****");
127  }
128  assert(res);
129  }
130  void clear(const std::string& channel) {
131  CARL_LOG_DEBUG("carl.checkpoint", "Clearing " << channel);
132  mChannels[channel].clear();
133  }
134  bool& mayExceed(const std::string& channel) {
135  return mChannels[channel].mayExceed;
136  }
137  bool& printDebug(const std::string& channel) {
138  return mChannels[channel].printDebug;
139  }
140  };
141 }
142 }
A small wrapper that configures logging for carl.
#define CARL_LOG_WARN(channel, msg)
Definition: carl-logging.h:41
#define CARL_LOG_ERROR(channel, msg)
Definition: carl-logging.h:40
#define CARL_LOG_DEBUG(channel, msg)
Definition: carl-logging.h:43
carl is the main namespace for the library.
std::string demangle(const char *name)
Definition: debug.cpp:19
std::tuple< std::decay_t< Args >... > Tuple
const std::string & description() const
std::tuple< std::string, bool, std::any > Checkpoint
const Checkpoint & cur() const
void add(const std::string &description, bool forced, Args &&... args)
bool & mayExceed(const std::string &channel)
CheckpointVector::Tuple< Args... > Tuple
void push(const std::string &channel, const std::string &description, bool forced, Args &&... args)
bool & printDebug(const std::string &channel)
std::map< std::string, CheckpointVector > Channels
bool check(const std::string &channel, const std::string &description, Args &&... args)
void clear(const std::string &channel)
void expect(const std::string &channel, const std::string &description, Args &&... args)
Base class that implements a singleton.
Definition: Singleton.h:24
static VariablePool & getInstance()
Returns the single instance of this class by reference.
Definition: Singleton.h:45