1// Copyright 2014 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
5#include "components/rappor/rappor_metric.h"
6
7#include <stdlib.h>
8
9#include "base/rand_util.h"
10#include "base/strings/stringprintf.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13namespace rappor {
14
15const RapporParameters kTestRapporParameters = {
16    1 /* Num cohorts */,
17    16 /* Bloom filter size bytes */,
18    4 /* Bloom filter hash count */,
19    PROBABILITY_75 /* Fake data probability */,
20    PROBABILITY_50 /* Fake one probability */,
21    PROBABILITY_75 /* One coin probability */,
22    PROBABILITY_50 /* Zero coin probability */};
23
24const RapporParameters kTestStatsRapporParameters = {
25    1 /* Num cohorts */,
26    50 /* Bloom filter size bytes */,
27    4 /* Bloom filter hash count */,
28    PROBABILITY_75 /* Fake data probability */,
29    PROBABILITY_50 /* Fake one probability */,
30    PROBABILITY_75 /* One coin probability */,
31    PROBABILITY_50 /* Zero coin probability */};
32
33// Check for basic syntax and use.
34TEST(RapporMetricTest, BasicMetric) {
35  RapporMetric testMetric("MyRappor", kTestRapporParameters, 0);
36  testMetric.AddSample("Bar");
37  EXPECT_EQ(0x80, testMetric.bytes()[1]);
38}
39
40TEST(RapporMetricTest, GetReport) {
41  RapporMetric metric("MyRappor", kTestRapporParameters, 0);
42
43  const ByteVector report = metric.GetReport(
44      HmacByteVectorGenerator::GenerateEntropyInput());
45  EXPECT_EQ(16u, report.size());
46}
47
48TEST(RapporMetricTest, GetReportStatistics) {
49  RapporMetric metric("MyStatsRappor", kTestStatsRapporParameters, 0);
50
51  ByteVector real_bits(kTestStatsRapporParameters.bloom_filter_size_bytes);
52  // Set 152 bits (19 bytes)
53  for (char i = 0; i < 19; i++) {
54    real_bits[i] = 0xff;
55  }
56  metric.SetBytesForTesting(real_bits);
57  const int real_bit_count = CountBits(real_bits);
58  EXPECT_EQ(real_bit_count, 152);
59
60  const std::string secret = HmacByteVectorGenerator::GenerateEntropyInput();
61  const ByteVector report = metric.GetReport(secret);
62
63  // For the bits we actually set in the Bloom filter, get a count of how
64  // many of them reported true.
65  ByteVector from_true_reports = report;
66  // Real bits AND report bits.
67  ByteVectorMerge(real_bits, real_bits, &from_true_reports);
68  const int true_from_true_count = CountBits(from_true_reports);
69
70  // For the bits we didn't set in the Bloom filter, get a count of how
71  // many of them reported true.
72  ByteVector from_false_reports = report;
73  ByteVectorOr(real_bits, &from_false_reports);
74  const int true_from_false_count =
75      CountBits(from_false_reports) - real_bit_count;
76
77  // The probability of a true bit being true after redaction =
78  //   [fake_prob]*[fake_true_prob] + (1-[fake_prob]) =
79  //   .75 * .5 + (1-.75) = .625
80  // The probablity of a false bit being true after redaction =
81  //   [fake_prob]*[fake_true_prob] = .375
82  // The probability of a bit reporting true =
83  //   [redacted_prob] * [one_coin_prob:.75] +
84  //      (1-[redacted_prob]) * [zero_coin_prob:.5] =
85  //   0.65625 for true bits
86  //   0.59375 for false bits
87
88  // stats.binom(152, 0.65625).ppf(0.000005) = 73
89  EXPECT_GT(true_from_true_count, 73);
90  // stats.binom(152, 0.65625).ppf(0.999995) = 124
91  EXPECT_LE(true_from_true_count, 124);
92
93  // stats.binom(248, 0.59375).ppf(.000005) = 113
94  EXPECT_GT(true_from_false_count, 113);
95  // stats.binom(248, 0.59375).ppf(.999995) = 181
96  EXPECT_LE(true_from_false_count, 181);
97}
98
99}  // namespace rappor
100