noisy_metrics_recorder_unittest.cc 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. // Copyright 2021 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/optimization_guide/core/noisy_metrics_recorder.h"
  5. #include <cmath>
  6. #include "base/check_op.h"
  7. #include "base/logging.h"
  8. #include "base/rand_util.h"
  9. #include "testing/gtest/include/gtest/gtest.h"
  10. // Tests that the original metric is returned as it is when the bit flip
  11. // probability is set to 0.
  12. TEST(NoisyMetricsRecorderTest, BasicsNoNoise) {
  13. const struct TestCase {
  14. uint32_t original_metric;
  15. uint8_t bits_count;
  16. } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
  17. for (const auto& test_case : kTestCases) {
  18. NoisyMetricsRecorder recorder;
  19. uint32_t flipped = recorder.GetNoisyMetric(0.0f, test_case.original_metric,
  20. test_case.bits_count);
  21. EXPECT_EQ(flipped, test_case.original_metric);
  22. }
  23. }
  24. // Tests that the original metric is within the expected bounds.
  25. TEST(NoisyMetricsRecorderTest, RandomNoise) {
  26. const struct TestCase {
  27. uint32_t original_metric;
  28. uint8_t bits_count;
  29. } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
  30. for (const auto& test_case : kTestCases) {
  31. NoisyMetricsRecorder recorder;
  32. uint32_t flipped = recorder.GetNoisyMetric(0.5f, test_case.original_metric,
  33. test_case.bits_count);
  34. EXPECT_GE(flipped, 0u);
  35. EXPECT_LE(static_cast<int>(flipped), std::pow(2, test_case.bits_count) - 1);
  36. }
  37. }
  38. // TestNoisyMetricsRecorder returns deterministic random number based on how
  39. // it's configured.
  40. class TestNoisyMetricsRecorder : public NoisyMetricsRecorder {
  41. public:
  42. enum class Mode { kAlternate0And1, kAll0, kAll1 };
  43. explicit TestNoisyMetricsRecorder(Mode mode) : mode_(mode) {}
  44. ~TestNoisyMetricsRecorder() = default;
  45. uint32_t GenerateNumberWithAlternate0And1Bits(size_t count_bits) const {
  46. int flipped_value = 0;
  47. int next_bit = 1;
  48. for (size_t i = 0; i < count_bits; ++i) {
  49. flipped_value |= (next_bit << i);
  50. next_bit = next_bit == 0 ? 1 : 0;
  51. }
  52. return flipped_value;
  53. }
  54. private:
  55. int GetRandEither0Or1() const override {
  56. if (mode_ == Mode::kAll0)
  57. return 0;
  58. if (mode_ == Mode::kAll1)
  59. return 1;
  60. if (last_bit_returned_ == 0) {
  61. last_bit_returned_ = 1;
  62. } else {
  63. last_bit_returned_ = 0;
  64. }
  65. return last_bit_returned_;
  66. }
  67. mutable int last_bit_returned_ = 0;
  68. const Mode mode_;
  69. };
  70. TEST(NoisyMetricsRecorderTest, All0s) {
  71. const struct TestCase {
  72. uint32_t original_metric;
  73. uint8_t bits_count;
  74. } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
  75. for (const auto& test_case : kTestCases) {
  76. TestNoisyMetricsRecorder recorder(TestNoisyMetricsRecorder::Mode::kAll0);
  77. uint32_t flipped = recorder.GetNoisyMetric(1.0f, test_case.original_metric,
  78. test_case.bits_count);
  79. EXPECT_EQ(flipped, 0u);
  80. }
  81. }
  82. TEST(NoisyMetricsRecorderTest, All1s) {
  83. const struct TestCase {
  84. uint32_t original_metric;
  85. uint8_t bits_count;
  86. } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
  87. for (const auto& test_case : kTestCases) {
  88. TestNoisyMetricsRecorder recorder(TestNoisyMetricsRecorder::Mode::kAll1);
  89. uint32_t flipped = recorder.GetNoisyMetric(1.0f, test_case.original_metric,
  90. test_case.bits_count);
  91. EXPECT_EQ(flipped, std::pow(2, test_case.bits_count) - 1);
  92. }
  93. }
  94. // Tests that the flipped return value matches the expected value. The noise is
  95. // added deterministically using TestNoisyMetricsRecorder.
  96. TEST(NoisyMetricsRecorderTest, AlternateBits) {
  97. const struct TestCase {
  98. uint32_t original_metric;
  99. uint8_t bits_count;
  100. } kTestCases[] = {{0, 1}, {1, 1}, {10, 4}, {10, 31}, {100, 7}, {4242, 31}};
  101. for (const auto& test_case : kTestCases) {
  102. TestNoisyMetricsRecorder recorder(
  103. TestNoisyMetricsRecorder::Mode::kAlternate0And1);
  104. uint32_t flipped = recorder.GetNoisyMetric(1.0f, test_case.original_metric,
  105. test_case.bits_count);
  106. EXPECT_EQ(flipped, recorder.GenerateNumberWithAlternate0And1Bits(
  107. test_case.bits_count));
  108. }
  109. }