Ocean
Loading...
Searching...
No Matches
ValidationPrecision.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_TEST_VALIDATION_PRECISION_H
9#define META_OCEAN_TEST_VALIDATION_PRECISION_H
10
11#include "ocean/test/Test.h"
13
15
16namespace Ocean
17{
18
19namespace Test
20{
21
22/**
23 * This class implements a helper class to validate the accuracy of tests.
24 * @see Validation.
25 * @ingroup test
26 */
28{
29 public:
30
31 /**
32 * Creates a new scoped iteration.
33 * By default the iteration is accurate enough.<br>
34 * Call setInaccurate() for an iteration which is not precise enough.
35 */
37 {
38 public:
39
40 /**
41 * Creates a new scoped iteration associated with a validation object.
42 */
44
45 /**
46 * Destructs this scoped object and forwards the information to the owning validation.
47 */
48 inline ~ScopedIteration();
49
50 /**
51 * Sets this iteration to be not precise enough.
52 */
53 inline void setInaccurate();
54
55 /**
56 * Sets this iteration to be not precise enough.
57 * This function will also write a message to the error log.
58 * @param expected The expected value
59 * @param actual The actual value
60 * @param file The source file in which the function call happens, e.g., __FILE__, must be valid
61 * @param line The line in the source file in which the function call happens, e.g., __LINE__, must be valid
62 * @tparam T The data type of the expected and actual value
63 */
64 template <typename T>
65 inline void setInaccurate(const T& expected, const T& actual, const char* file, const int line);
66
67 protected:
68
69 /**
70 * Disabled default constructor.
71 */
72 ScopedIteration() = delete;
73
74 /**
75 * Disabled copy constructor.
76 */
78
79 /**
80 * Disabled move constructor.
81 */
83
84 protected:
85
86 /// True, if the iteration is accurate; False, if the iteration was not accurate enough.
87 bool accurate_ = true;
88
89 /// The owner of this scoped object.
91 };
92
93 public:
94
95 /**
96 * Creates a new precision-based validation object with specified threshold.
97 * @param threshold The necessary percent of accurate iterations necessary for a successful verification, with range (0, 1]
98 * @param minimumIterations The minimum number of iterations necessary for a successful verification, with range [1, infinity)
99 */
100 explicit inline ValidationPrecision(const double threshold, const unsigned int minimumIterations = 1u);
101
102 /**
103 * Creates a new validation object associated with a random generator, by default the verified has succeeded.
104 * @param threshold The necessary percent of accurate iterations necessary for a successful verification, with range (0, 1]
105 * @param randomGenerator The random generator which will be used during verification
106 */
107 inline ValidationPrecision(const double threshold, RandomGenerator& randomGenerator, const unsigned int minimumIterations = 1u);
108
109 /**
110 * Destructs this validation object.
111 */
112 inline ~ValidationPrecision();
113
114 /**
115 * Explicitly adds a new iteration which is either accurate or not.
116 * @param accurate True, if the iteration was precise enough; False, if the iteration was not precise enough
117 * @see ScopedIteration.
118 */
119 inline void addIteration(const bool accurate);
120
121 /**
122 * Explicitly adds new iterations for which the amount of accurate iterations is known.
123 * @param accurateIterations The number of accurate iterations, with range [0, iterations]
124 * @param iterations The number of new iterations, with range [1, infinity)
125 * @see ScopedIteration.
126 */
127 inline void addIterations(const size_t accurateIterations, const size_t iterations);
128
129 /**
130 * Explicitly sets the validation to be failed.
131 * Setting this validation to be failed will result in a failed validation even if all iteration were precise enough.
132 * @see succeeded().
133 */
134 inline void setFailed();
135
136 /**
137 * Explicitly sets the validation to be failed.
138 * Setting this validation to be failed will result in a failed validation even if all iteration were precise enough.
139 * @param file The source file in which the function call happens, e.g., __FILE__, must be valid
140 * @param line The line in the source file in which the function call happens, e.g., __LINE__, must be valid
141 * @see succeeded().
142 */
143 inline void setFailed(const char* file, const int line);
144
145 /**
146 * Returns the number of iterations in which the precision has been determined.
147 * @return The number of iterations, with range [0, infinity)
148 */
149 inline uint64_t iterations() const;
150
151 /**
152 * Returns the necessary iterations to allow determining success or failure based on the specified success threshold.
153 * @return The number of necessary iterations, with range [1, infinity)
154 */
155 inline uint64_t necessaryIterations() const;
156
157 /**
158 * Returns whether the number of iterations is not yet sufficient to determine a success or failure.
159 * @return True, if more iterations are required
160 */
161 inline bool needMoreIterations() const;
162
163 /**
164 * Returns if this validation has succeeded.
165 * @return True, if so; False, if the validation has failed
166 */
167 [[nodiscard]] inline bool succeeded() const;
168
169 /**
170 * Returns the accuracy of all iterations.
171 * Beware: Ensure that at least one iteration has been added.
172 * @return The validation's accuracy, in percent, with range [0, 1]
173 */
174 [[nodiscard]] inline double accuracy() const;
175
176 /**
177 * Returns the defined threshold.
178 * @return The validation object's precision threshold, with range [0, 1]
179 */
180 inline double threshold() const;
181
182 /**
183 * Returns whether this validation object has been set to failed explicitly.
184 * This function is intended for internal use only, use succeeded() instead.
185 * @return True, if so
186 * @see succeeded().
187 */
188 [[nodiscard]] inline bool hasSetFailed() const;
189
190 /**
191 * Returns a string containing the random generator's initial seed, if any
192 * @return The string with initial seed test, empty if no random generator is associated with this validation object
193 */
194 inline std::string randomGeneratorOutput() const;
195
196 protected:
197
198 /**
199 * Disabled copy constructor.
200 */
202
203 /**
204 * Sets the succeeded state to false.
205 */
206 inline void setSucceededFalse();
207
208 protected:
209
210 /// The necessary percent of accurate iterations necessary for a successful verification, with range (0, 1]
211 double threshold_ = 1.0;
212
213 /// True, if the validation has succeeded; False, if the validation has failed.
214 bool succeeded_ = true;
215
216 /// The number of iterations needed to determine success or failure.
217 uint64_t necessaryIterations_ = 0ull;
218
219 /// The overall number of iterations which have been added.
220 uint64_t iterations_ = 0ull;
221
222 /// The number of iterations which were precise enough, with range [0, iterations_]
223 uint64_t accurateIterations_ = 0ull;
224
225 /// Optional random generator object which will be used during validation.
227
228#ifdef OCEAN_DEBUG
229 /// True, if the success state of this validation has been checked.
230 mutable bool succeededChecked_ = false;
231#endif // OCEAN_DEBUG
232};
233
234#ifndef OCEAN_SET_INACCURATE
235 #define OCEAN_SET_INACCURATE(scopedIteration, expected, actual) scopedIteration.setInaccurate(expected, actual, __FILE__, __LINE__);
236#endif
237
239 validationPrecision_(ValidationPrecision)
240{
241 // nothing to do here
242}
243
245{
246 validationPrecision_.addIteration(accurate_);
247}
248
250{
251 accurate_ = false;
252}
253
254template <typename T>
255inline void ValidationPrecision::ScopedIteration::setInaccurate(const T& expected, const T& actual, const char* file, const int line)
256{
257 accurate_ = false;
258
259 ocean_assert(file != nullptr);
260 if (file != nullptr)
261 {
262 Log::error() << "ScopedIteration::setInaccurate() in '" << file << "', in line " << line << ": expected " << expected << ", got " << actual << validationPrecision_.randomGeneratorOutput();
263 }
264}
265
266inline ValidationPrecision::ValidationPrecision(const double threshold, const unsigned int minimumIterations)
267{
268 ocean_assert(threshold > 0.0 && threshold <= 1.0);
269
270 if (threshold > 0.0 && threshold <= 1.0)
271 {
273
274 const double failureRate = 1.0 - threshold_;
275 ocean_assert(failureRate > 0.0);
276
277 const double idealIterations = 1.0 / failureRate;
278
279 ocean_assert(idealIterations <= 1000000000u);
280 necessaryIterations_ = std::max(minimumIterations, (unsigned int)(std::ceil(idealIterations) * 2.0));
281 }
282 else
283 {
285 }
286}
287
288inline ValidationPrecision::ValidationPrecision(const double threshold, RandomGenerator& randomGenerator, const unsigned int minimumIterations) :
289 ValidationPrecision(threshold, minimumIterations)
290{
291 randomGenerator_ = &randomGenerator;
292}
293
295{
296#ifdef OCEAN_DEBUG
297 ocean_assert(succeededChecked_ && "The verifier has not been check for success");
298#endif
299}
300
301inline void ValidationPrecision::addIteration(const bool accurate)
302{
303 ++iterations_;
304
305 if (accurate)
306 {
308 }
309}
310
311inline void ValidationPrecision::addIterations(const size_t accurateIterations, const size_t iterations)
312{
313 ocean_assert(accurateIterations <= iterations);
314 ocean_assert(iterations >= 1);
315
316 if (accurateIterations > iterations)
317 {
319 }
320
321 accurateIterations_ += accurateIterations;
323}
324
329
330inline void ValidationPrecision::setFailed(const char* file, const int line)
331{
333
334 ocean_assert(file != nullptr);
335 if (file != nullptr)
336 {
337#ifdef OCEAN_USE_GTEST
338 std::cerr << "\nValidationPrecision::setFailed() in '" << file << "', in line " << line << randomGeneratorOutput() << "\n" << std::endl;
339#else
340 Log::error() << "ValidationPrecision::setFailed() in '" << file << "', in line " << line << randomGeneratorOutput();
341#endif
342 }
343}
344
345inline uint64_t ValidationPrecision::iterations() const
346{
347 return iterations_;
348}
349
351{
352 ocean_assert(necessaryIterations_ >= 1ull);
353
355}
356
358{
359 ocean_assert(necessaryIterations_ >= 1ull);
360
362}
363
365{
366#ifdef OCEAN_DEBUG
367 succeededChecked_ = true;
368#endif
369
370 ocean_assert(threshold_ > 0.0 && threshold_ <= 1.0);
371
372 if (threshold_ <= 0.0 || threshold_ > 1.0)
373 {
374 return false;
375 }
376
377 const double percent = accuracy();
378
379 if (percent < threshold_)
380 {
381#ifdef OCEAN_USE_GTEST
382
383 std::ostream& stream = std::cerr << "\nFAILED with only " << String::toAString(accuracy() * 100.0, 1u) << "%, threshold is " << String::toAString(threshold() * 100.0, 1u) << "%" << randomGeneratorOutput() << "\n";
384
385 if (needMoreIterations())
386 {
387 stream << "Not enough iterations for the specified success threshold (executed " << iterations_ << " of " << necessaryIterations_ << " necessary iterations)\n";
388 }
389
390 stream << std::endl;
391#endif
392 return false;
393 }
394
395 return succeeded_;
396}
397
398[[nodiscard]] inline double ValidationPrecision::accuracy() const
399{
400 ocean_assert(iterations_ != 0ull);
401
402 if (iterations_ == 0u)
403 {
404 return -1.0;
405 }
406
407 ocean_assert(accurateIterations_ <= iterations_);
408
409 const double percent = double(accurateIterations_) / double(iterations_);
410 ocean_assert(percent >= 0.0 && percent <= 1.0);
411
412 return percent;
413}
414
416{
417 return threshold_;
418}
419
420[[nodiscard]] inline bool ValidationPrecision::hasSetFailed() const
421{
422 return succeeded_ == false;
423}
424
426{
427 if (randomGenerator_ != nullptr)
428 {
429 return ", with random generator initial seed '" + String::toAString(randomGenerator_->initialSeed()) + "'";
430 }
431
432 return std::string();
433}
434
436{
437 succeeded_ = false;
438}
439
440inline std::ostream& operator<<(std::ostream& stream, const ValidationPrecision& validation)
441{
442 if (validation.hasSetFailed())
443 {
444 stream << "FAILED!" << validation.randomGeneratorOutput();
445 }
446 else
447 {
448 if (validation.accuracy() < validation.threshold())
449 {
450 stream << "FAILED with only " << String::toAString(validation.accuracy() * 100.0, 1u) << "%, threshold is " << String::toAString(validation.threshold() * 100.0, 1u) << "%" << validation.randomGeneratorOutput();
451 }
452 else
453 {
454 stream << String::toAString(validation.accuracy() * 100.0, 1u) << "% succeeded.";
455 }
456 }
457
458 return stream;
459}
460
461template <bool tActive>
462MessageObject<tActive>& operator<<(MessageObject<tActive>& messageObject, const ValidationPrecision& validation)
463{
464 if (validation.hasSetFailed())
465 {
466 messageObject << "FAILED!" << validation.randomGeneratorOutput();
467 }
468 else
469 {
470 if (validation.accuracy() < validation.threshold())
471 {
472 messageObject << "FAILED with only " << String::toAString(validation.accuracy() * 100.0, 1u) << "%, threshold is " << String::toAString(validation.threshold() * 100.0, 1u) << "%" << validation.randomGeneratorOutput();
473 }
474 else
475 {
476 messageObject << String::toAString(validation.accuracy() * 100.0, 1u) << "% succeeded.";
477 }
478 }
479
480 return messageObject;
481}
482
483template <bool tActive>
484MessageObject<tActive>& operator<<(MessageObject<tActive>&& messageObject, const ValidationPrecision& validation)
485{
486 if (validation.hasSetFailed())
487 {
488 messageObject << "FAILED!" << validation.randomGeneratorOutput();
489 }
490 else
491 {
492 if (validation.accuracy() < validation.threshold())
493 {
494 messageObject << "FAILED with only " << String::toAString(validation.accuracy() * 100.0, 1u) << "%, threshold is " << String::toAString(validation.threshold() * 100.0, 1u) << "%" << validation.randomGeneratorOutput();
495 }
496 else
497 {
498 messageObject << String::toAString(validation.accuracy() * 100.0, 1u) << "% succeeded.";
499 }
500 }
501
502 return messageObject;
503}
504
505}
506
507}
508
509#endif // META_OCEAN_TEST_VALIDATION_PRECISION_H
static MessageObject error()
Returns the message for error messages.
Definition Messenger.h:1074
Messenger object, one object for each message.
Definition Messenger.h:427
This class implements a generator for random numbers.
Definition RandomGenerator.h:42
unsigned int initialSeed() const
Returns the initial seed value which was used to initialize this random generator.
Definition RandomGenerator.h:178
static std::string toAString(const char value)
Converts a value to a string with 8bit character.
Creates a new scoped iteration.
Definition ValidationPrecision.h:37
ScopedIteration(const ScopedIteration &&)=delete
Disabled move constructor.
void setInaccurate()
Sets this iteration to be not precise enough.
Definition ValidationPrecision.h:249
ValidationPrecision & validationPrecision_
The owner of this scoped object.
Definition ValidationPrecision.h:90
ScopedIteration(const ScopedIteration &)=delete
Disabled copy constructor.
bool accurate_
True, if the iteration is accurate; False, if the iteration was not accurate enough.
Definition ValidationPrecision.h:87
~ScopedIteration()
Destructs this scoped object and forwards the information to the owning validation.
Definition ValidationPrecision.h:244
ScopedIteration()=delete
Disabled default constructor.
This class implements a helper class to validate the accuracy of tests.
Definition ValidationPrecision.h:28
double threshold() const
Returns the defined threshold.
Definition ValidationPrecision.h:415
void addIterations(const size_t accurateIterations, const size_t iterations)
Explicitly adds new iterations for which the amount of accurate iterations is known.
Definition ValidationPrecision.h:311
uint64_t iterations_
The overall number of iterations which have been added.
Definition ValidationPrecision.h:220
ValidationPrecision(const double threshold, const unsigned int minimumIterations=1u)
Creates a new precision-based validation object with specified threshold.
Definition ValidationPrecision.h:266
RandomGenerator * randomGenerator_
Optional random generator object which will be used during validation.
Definition ValidationPrecision.h:226
uint64_t accurateIterations_
The number of iterations which were precise enough, with range [0, iterations_].
Definition ValidationPrecision.h:223
std::string randomGeneratorOutput() const
Returns a string containing the random generator's initial seed, if any.
Definition ValidationPrecision.h:425
bool needMoreIterations() const
Returns whether the number of iterations is not yet sufficient to determine a success or failure.
Definition ValidationPrecision.h:357
bool succeeded_
True, if the validation has succeeded; False, if the validation has failed.
Definition ValidationPrecision.h:214
double accuracy() const
Returns the accuracy of all iterations.
Definition ValidationPrecision.h:398
void setSucceededFalse()
Sets the succeeded state to false.
Definition ValidationPrecision.h:435
void addIteration(const bool accurate)
Explicitly adds a new iteration which is either accurate or not.
Definition ValidationPrecision.h:301
~ValidationPrecision()
Destructs this validation object.
Definition ValidationPrecision.h:294
ValidationPrecision(const ValidationPrecision &)=delete
Disabled copy constructor.
uint64_t necessaryIterations() const
Returns the necessary iterations to allow determining success or failure based on the specified succe...
Definition ValidationPrecision.h:350
bool succeeded() const
Returns if this validation has succeeded.
Definition ValidationPrecision.h:364
double threshold_
The necessary percent of accurate iterations necessary for a successful verification,...
Definition ValidationPrecision.h:211
uint64_t iterations() const
Returns the number of iterations in which the precision has been determined.
Definition ValidationPrecision.h:345
bool succeededChecked_
True, if the success state of this validation has been checked.
Definition ValidationPrecision.h:230
uint64_t necessaryIterations_
The number of iterations needed to determine success or failure.
Definition ValidationPrecision.h:217
bool hasSetFailed() const
Returns whether this validation object has been set to failed explicitly.
Definition ValidationPrecision.h:420
void setFailed()
Explicitly sets the validation to be failed.
Definition ValidationPrecision.h:325
std::ostream & operator<<(std::ostream &stream, const Validation &validation)
Definition Validation.h:824
The namespace covering the entire Ocean framework.
Definition Accessor.h:15