1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #include <math.h>
8 
9 #include "gtest/gtest.h"
10 #include "nsIPrefBranch.h"
11 #include "nsServiceManagerUtils.h"
12 #include "nsRFPService.h"
13 
14 using namespace mozilla;
15 
16 // clang-format off
17 /*
18    Hello! Are you looking at this file because you got an error you don't understand?
19    Perhaps something that looks like the following?
20 
21     toolkit/components/resistfingerprinting/tests/test_reduceprecision.cpp:15: Failure
22       Expected: reduced1
23         Which is: 2064.83
24       To be equal to: reduced2
25         Which is: 2064.83
26 
27    "Gosh," you might say, "They sure look equal to me. What the heck is going on here?"
28 
29    The answer lies beyond what you can see, in that which you cannot see. One must
30    journey into the depths, the hidden, that which the world fights its hardest to
31    conceal from us.
32 
33    Specially: you need to look at more decimal places. Run the test with:
34        MOZ_LOG="nsResistFingerprinting:5"
35 
36    And look for two successive lines similar to the below (the format will certainly
37    be different by the time you read this comment):
38       V/nsResistFingerprinting Given: 2064.83384599999999, Reciprocal Rounding with 50000.00000000000000, Intermediate: 103241692.00000000000000, Got: 2064.83383999999978
39       V/nsResistFingerprinting Given: 2064.83383999999978, Reciprocal Rounding with 50000.00000000000000, Intermediate: 103241691.00000000000000, Got: 2064.83381999999983
40 
41    Look at the last two values:
42       Got: 2064.83383999999978
43       Got: 2064.83381999999983
44 
45    They're supposed to be equal. They're not. But they both round to 2064.83.
46 */
47 // clang-format on
48 
setupJitter(bool enabled)49 bool setupJitter(bool enabled) {
50   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
51 
52   bool jitterEnabled = false;
53   if (prefs) {
54     prefs->GetBoolPref(
55         "privacy.resistFingerprinting.reduceTimerPrecision.jitter",
56         &jitterEnabled);
57     prefs->SetBoolPref(
58         "privacy.resistFingerprinting.reduceTimerPrecision.jitter", enabled);
59   }
60 
61   return jitterEnabled;
62 }
63 
cleanupJitter(bool jitterWasEnabled)64 void cleanupJitter(bool jitterWasEnabled) {
65   nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
66   if (prefs) {
67     prefs->SetBoolPref(
68         "privacy.resistFingerprinting.reduceTimerPrecision.jitter",
69         jitterWasEnabled);
70   }
71 }
72 
process(double clock,nsRFPService::TimeScale clockUnits,double precision)73 void process(double clock, nsRFPService::TimeScale clockUnits,
74              double precision) {
75   double reduced1 = nsRFPService::ReduceTimePrecisionImpl(
76       clock, clockUnits, precision, -1, TimerPrecisionType::Normal);
77   double reduced2 = nsRFPService::ReduceTimePrecisionImpl(
78       reduced1, clockUnits, precision, -1, TimerPrecisionType::Normal);
79   ASSERT_EQ(reduced1, reduced2);
80 }
81 
TEST(ResistFingerprinting,ReducePrecision_Assumptions)82 TEST(ResistFingerprinting, ReducePrecision_Assumptions)
83 {
84   ASSERT_EQ(FLT_RADIX, 2);
85   ASSERT_EQ(DBL_MANT_DIG, 53);
86 }
87 
TEST(ResistFingerprinting,ReducePrecision_Reciprocal)88 TEST(ResistFingerprinting, ReducePrecision_Reciprocal)
89 {
90   bool jitterEnabled = setupJitter(false);
91   // This one has a rounding error in the Reciprocal case:
92   process(2064.8338460, nsRFPService::TimeScale::MicroSeconds, 20);
93   // These are just big values
94   process(1516305819, nsRFPService::TimeScale::MicroSeconds, 20);
95   process(69053.12, nsRFPService::TimeScale::MicroSeconds, 20);
96   cleanupJitter(jitterEnabled);
97 }
98 
TEST(ResistFingerprinting,ReducePrecision_KnownGood)99 TEST(ResistFingerprinting, ReducePrecision_KnownGood)
100 {
101   bool jitterEnabled = setupJitter(false);
102   process(2064.8338460, nsRFPService::TimeScale::MilliSeconds, 20);
103   process(69027.62, nsRFPService::TimeScale::MilliSeconds, 20);
104   process(69053.12, nsRFPService::TimeScale::MilliSeconds, 20);
105   cleanupJitter(jitterEnabled);
106 }
107 
TEST(ResistFingerprinting,ReducePrecision_KnownBad)108 TEST(ResistFingerprinting, ReducePrecision_KnownBad)
109 {
110   bool jitterEnabled = setupJitter(false);
111   process(1054.842405, nsRFPService::TimeScale::MilliSeconds, 20);
112   process(273.53038600000002, nsRFPService::TimeScale::MilliSeconds, 20);
113   process(628.66686500000003, nsRFPService::TimeScale::MilliSeconds, 20);
114   process(521.28919100000007, nsRFPService::TimeScale::MilliSeconds, 20);
115   cleanupJitter(jitterEnabled);
116 }
117 
TEST(ResistFingerprinting,ReducePrecision_Edge)118 TEST(ResistFingerprinting, ReducePrecision_Edge)
119 {
120   bool jitterEnabled = setupJitter(false);
121   process(2611.14, nsRFPService::TimeScale::MilliSeconds, 20);
122   process(2611.16, nsRFPService::TimeScale::MilliSeconds, 20);
123   process(2612.16, nsRFPService::TimeScale::MilliSeconds, 20);
124   process(2601.64, nsRFPService::TimeScale::MilliSeconds, 20);
125   process(2595.16, nsRFPService::TimeScale::MilliSeconds, 20);
126   process(2578.66, nsRFPService::TimeScale::MilliSeconds, 20);
127   cleanupJitter(jitterEnabled);
128 }
129 
TEST(ResistFingerprinting,ReducePrecision_Expectations)130 TEST(ResistFingerprinting, ReducePrecision_Expectations)
131 {
132   bool jitterEnabled = setupJitter(false);
133   double result;
134   result = nsRFPService::ReduceTimePrecisionImpl(
135       2611.14, nsRFPService::TimeScale::MilliSeconds, 20, -1,
136       TimerPrecisionType::Normal);
137   ASSERT_EQ(result, 2611.14);
138   result = nsRFPService::ReduceTimePrecisionImpl(
139       2611.145, nsRFPService::TimeScale::MilliSeconds, 20, -1,
140       TimerPrecisionType::Normal);
141   ASSERT_EQ(result, 2611.14);
142   result = nsRFPService::ReduceTimePrecisionImpl(
143       2611.141, nsRFPService::TimeScale::MilliSeconds, 20, -1,
144       TimerPrecisionType::Normal);
145   ASSERT_EQ(result, 2611.14);
146   result = nsRFPService::ReduceTimePrecisionImpl(
147       2611.15999, nsRFPService::TimeScale::MilliSeconds, 20, -1,
148       TimerPrecisionType::Normal);
149   ASSERT_EQ(result, 2611.14);
150   result = nsRFPService::ReduceTimePrecisionImpl(
151       2611.15, nsRFPService::TimeScale::MilliSeconds, 20, -1,
152       TimerPrecisionType::Normal);
153   ASSERT_EQ(result, 2611.14);
154   result = nsRFPService::ReduceTimePrecisionImpl(
155       2611.13, nsRFPService::TimeScale::MilliSeconds, 20, -1,
156       TimerPrecisionType::Normal);
157   ASSERT_EQ(result, 2611.12);
158   cleanupJitter(jitterEnabled);
159 }
160 
TEST(ResistFingerprinting,ReducePrecision_Expectations_HighRes)161 TEST(ResistFingerprinting, ReducePrecision_Expectations_HighRes)
162 {
163   bool jitterEnabled = setupJitter(false);
164   double result;
165   result = nsRFPService::ReduceTimePrecisionImpl(
166       2611.14, nsRFPService::TimeScale::MilliSeconds, 20, -1,
167       TimerPrecisionType::UnconditionalAKAHighRes);
168   ASSERT_EQ(result, 2611.14);
169   result = nsRFPService::ReduceTimePrecisionImpl(
170       2611.145, nsRFPService::TimeScale::MilliSeconds, 20, -1,
171       TimerPrecisionType::UnconditionalAKAHighRes);
172   ASSERT_EQ(result, 2611.14);
173   result = nsRFPService::ReduceTimePrecisionImpl(
174       2611.141, nsRFPService::TimeScale::MilliSeconds, 20, -1,
175       TimerPrecisionType::UnconditionalAKAHighRes);
176   ASSERT_EQ(result, 2611.14);
177   result = nsRFPService::ReduceTimePrecisionImpl(
178       2611.15999, nsRFPService::TimeScale::MilliSeconds, 20, -1,
179       TimerPrecisionType::UnconditionalAKAHighRes);
180   ASSERT_EQ(result, 2611.14);
181   result = nsRFPService::ReduceTimePrecisionImpl(
182       2611.15, nsRFPService::TimeScale::MilliSeconds, 20, -1,
183       TimerPrecisionType::UnconditionalAKAHighRes);
184   ASSERT_EQ(result, 2611.14);
185   result = nsRFPService::ReduceTimePrecisionImpl(
186       2611.13, nsRFPService::TimeScale::MilliSeconds, 20, -1,
187       TimerPrecisionType::UnconditionalAKAHighRes);
188   ASSERT_EQ(result, 2611.12);
189   cleanupJitter(jitterEnabled);
190 }
191 
TEST(ResistFingerprinting,ReducePrecision_Expectations_RFP)192 TEST(ResistFingerprinting, ReducePrecision_Expectations_RFP)
193 {
194   bool jitterEnabled = setupJitter(false);
195   double result;
196   result = nsRFPService::ReduceTimePrecisionImpl(
197       2611.14, nsRFPService::TimeScale::MilliSeconds, 20, -1,
198       TimerPrecisionType::RFP);
199   ASSERT_EQ(result, 2611.14);
200   result = nsRFPService::ReduceTimePrecisionImpl(
201       2611.145, nsRFPService::TimeScale::MilliSeconds, 20, -1,
202       TimerPrecisionType::RFP);
203   ASSERT_EQ(result, 2611.14);
204   result = nsRFPService::ReduceTimePrecisionImpl(
205       2611.141, nsRFPService::TimeScale::MilliSeconds, 20, -1,
206       TimerPrecisionType::RFP);
207   ASSERT_EQ(result, 2611.14);
208   result = nsRFPService::ReduceTimePrecisionImpl(
209       2611.15999, nsRFPService::TimeScale::MilliSeconds, 20, -1,
210       TimerPrecisionType::RFP);
211   ASSERT_EQ(result, 2611.14);
212   result = nsRFPService::ReduceTimePrecisionImpl(
213       2611.15, nsRFPService::TimeScale::MilliSeconds, 20, -1,
214       TimerPrecisionType::RFP);
215   ASSERT_EQ(result, 2611.14);
216   result = nsRFPService::ReduceTimePrecisionImpl(
217       2611.13, nsRFPService::TimeScale::MilliSeconds, 20, -1,
218       TimerPrecisionType::RFP);
219   ASSERT_EQ(result, 2611.12);
220   cleanupJitter(jitterEnabled);
221 }
222 
TEST(ResistFingerprinting,ReducePrecision_Expectations_DangerouslyNone)223 TEST(ResistFingerprinting, ReducePrecision_Expectations_DangerouslyNone)
224 {
225   bool jitterEnabled = setupJitter(false);
226   double result;
227   result = nsRFPService::ReduceTimePrecisionImpl(
228       2611.14, nsRFPService::TimeScale::MilliSeconds, 20, -1,
229       TimerPrecisionType::DangerouslyNone);
230   ASSERT_EQ(result, 2611.14);
231   result = nsRFPService::ReduceTimePrecisionImpl(
232       2611.145, nsRFPService::TimeScale::MilliSeconds, 20, -1,
233       TimerPrecisionType::DangerouslyNone);
234   ASSERT_EQ(result, 2611.145);
235   result = nsRFPService::ReduceTimePrecisionImpl(
236       2611.141, nsRFPService::TimeScale::MilliSeconds, 20, -1,
237       TimerPrecisionType::DangerouslyNone);
238   ASSERT_EQ(result, 2611.141);
239   result = nsRFPService::ReduceTimePrecisionImpl(
240       2611.15999, nsRFPService::TimeScale::MilliSeconds, 20, -1,
241       TimerPrecisionType::DangerouslyNone);
242   ASSERT_EQ(result, 2611.15999);
243   result = nsRFPService::ReduceTimePrecisionImpl(
244       2611.15, nsRFPService::TimeScale::MilliSeconds, 20, -1,
245       TimerPrecisionType::DangerouslyNone);
246   ASSERT_EQ(result, 2611.15);
247   result = nsRFPService::ReduceTimePrecisionImpl(
248       2611.13, nsRFPService::TimeScale::MilliSeconds, 20, -1,
249       TimerPrecisionType::DangerouslyNone);
250   ASSERT_EQ(result, 2611.13);
251   cleanupJitter(jitterEnabled);
252 }
253 
TEST(ResistFingerprinting,ReducePrecision_ExpectedLossOfPrecision)254 TEST(ResistFingerprinting, ReducePrecision_ExpectedLossOfPrecision)
255 {
256   bool jitterEnabled = setupJitter(false);
257   double result;
258   // We lose integer precision at 9007199254740992 - let's confirm that.
259   result = nsRFPService::ReduceTimePrecisionImpl(
260       9007199254740992.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
261       TimerPrecisionType::Normal);
262   ASSERT_EQ(result, 9007199254740990.0);
263   // 9007199254740995 is approximated to 9007199254740996
264   result = nsRFPService::ReduceTimePrecisionImpl(
265       9007199254740995.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
266       TimerPrecisionType::Normal);
267   ASSERT_EQ(result, 9007199254740996);
268   // 9007199254740999 is approximated as 9007199254741000
269   result = nsRFPService::ReduceTimePrecisionImpl(
270       9007199254740999.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
271       TimerPrecisionType::Normal);
272   ASSERT_EQ(result, 9007199254741000.0);
273   // 9007199254743568 can be represented exactly, but will be clamped to
274   // 9007199254743564
275   result = nsRFPService::ReduceTimePrecisionImpl(
276       9007199254743568.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
277       TimerPrecisionType::Normal);
278   ASSERT_EQ(result, 9007199254743564.0);
279   cleanupJitter(jitterEnabled);
280 }
281 
TEST(ResistFingerprinting,ReducePrecision_ExpectedLossOfPrecision_HighRes)282 TEST(ResistFingerprinting, ReducePrecision_ExpectedLossOfPrecision_HighRes)
283 {
284   bool jitterEnabled = setupJitter(false);
285   double result;
286   // We lose integer precision at 9007199254740992 - let's confirm that.
287   result = nsRFPService::ReduceTimePrecisionImpl(
288       9007199254740992.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
289       TimerPrecisionType::UnconditionalAKAHighRes);
290   ASSERT_EQ(result, 9007199254740980.0);
291   // 9007199254740995 is approximated to 9007199254740980
292   result = nsRFPService::ReduceTimePrecisionImpl(
293       9007199254740995.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
294       TimerPrecisionType::UnconditionalAKAHighRes);
295   ASSERT_EQ(result, 9007199254740980);
296   // 9007199254740999 is approximated as 9007199254741000
297   result = nsRFPService::ReduceTimePrecisionImpl(
298       9007199254740999.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
299       TimerPrecisionType::UnconditionalAKAHighRes);
300   ASSERT_EQ(result, 9007199254741000.0);
301   // 9007199254743568 can be represented exactly, but will be clamped to
302   // 9007199254743560
303   result = nsRFPService::ReduceTimePrecisionImpl(
304       9007199254743568.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
305       TimerPrecisionType::UnconditionalAKAHighRes);
306   ASSERT_EQ(result, 9007199254743560.0);
307   cleanupJitter(jitterEnabled);
308 }
309 
TEST(ResistFingerprinting,ReducePrecision_ExpectedLossOfPrecision_RFP)310 TEST(ResistFingerprinting, ReducePrecision_ExpectedLossOfPrecision_RFP)
311 {
312   bool jitterEnabled = setupJitter(false);
313   double result;
314   // We lose integer precision at 9007199254740992 - let's confirm that.
315   result = nsRFPService::ReduceTimePrecisionImpl(
316       9007199254740992.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
317       TimerPrecisionType::RFP);
318   ASSERT_EQ(result, 9007199254740990.0);
319   // 9007199254740995 is approximated to 9007199254740980
320   result = nsRFPService::ReduceTimePrecisionImpl(
321       9007199254740995.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
322       TimerPrecisionType::RFP);
323   ASSERT_EQ(result, 9007199254740995);
324   // 9007199254740999 is approximated as 9007199254741000
325   result = nsRFPService::ReduceTimePrecisionImpl(
326       9007199254740999.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
327       TimerPrecisionType::RFP);
328   ASSERT_EQ(result, 9007199254741000.0);
329   // 9007199254743568 can be represented exactly, but will be clamped to
330   // 9007199254743560
331   result = nsRFPService::ReduceTimePrecisionImpl(
332       9007199254743568.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
333       TimerPrecisionType::RFP);
334   ASSERT_EQ(result, 9007199254743565.0);
335   cleanupJitter(jitterEnabled);
336 }
337 
TEST(ResistFingerprinting,ReducePrecision_ExpectedLossOfPrecision_DangerouslyNone)338 TEST(ResistFingerprinting,
339      ReducePrecision_ExpectedLossOfPrecision_DangerouslyNone)
340 {
341   bool jitterEnabled = setupJitter(false);
342   double result;
343   // We lose integer precision at 9007199254740992 - let's confirm that.
344   result = nsRFPService::ReduceTimePrecisionImpl(
345       9007199254740992.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
346       TimerPrecisionType::DangerouslyNone);
347   ASSERT_EQ(result, 9007199254740992.0);
348   // 9007199254740995 is approximated to 9007199254740980
349   result = nsRFPService::ReduceTimePrecisionImpl(
350       9007199254740995.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
351       TimerPrecisionType::DangerouslyNone);
352   ASSERT_EQ(result, 9007199254740995);
353   // 9007199254740999 is approximated as 9007199254741000
354   result = nsRFPService::ReduceTimePrecisionImpl(
355       9007199254740999.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
356       TimerPrecisionType::DangerouslyNone);
357   ASSERT_EQ(result, 9007199254740999.0);
358   // 9007199254743568 can be represented exactly, but will be clamped to
359   // 9007199254743560
360   result = nsRFPService::ReduceTimePrecisionImpl(
361       9007199254743568.0, nsRFPService::TimeScale::MicroSeconds, 5, -1,
362       TimerPrecisionType::DangerouslyNone);
363   ASSERT_EQ(result, 9007199254743568.0);
364   cleanupJitter(jitterEnabled);
365 }
366 
367 // Use an ugly but simple hack to turn an integer-based rand()
368 // function to a double-based one.
369 #define RAND_DOUBLE (rand() * (rand() / (double)rand()))
370 
371 // If you're doing logging, you really don't want to run this test.
372 #define RUN_AGGRESSIVE false
373 
TEST(ResistFingerprinting,ReducePrecision_Aggressive)374 TEST(ResistFingerprinting, ReducePrecision_Aggressive)
375 {
376   if (!RUN_AGGRESSIVE) {
377     return;
378   }
379 
380   bool jitterEnabled = setupJitter(false);
381 
382   for (int i = 0; i < 10000; i++) {
383     // Test three different time magnitudes, with decimals.
384     // Note that we need separate variables for the different units, as scaling
385     // them after calculating them will erase effects of approximation.
386     // A magnitude in the seconds since epoch range.
387     double time1_s = fmod(RAND_DOUBLE, 1516305819.0);
388     double time1_ms = fmod(RAND_DOUBLE, 1516305819000.0);
389     double time1_us = fmod(RAND_DOUBLE, 1516305819000000.0);
390     // A magnitude in the 'couple of minutes worth of milliseconds' range.
391     double time2_s = fmod(RAND_DOUBLE, (60.0 * 60 * 5));
392     double time2_ms = fmod(RAND_DOUBLE, (1000.0 * 60 * 60 * 5));
393     double time2_us = fmod(RAND_DOUBLE, (1000000.0 * 60 * 60 * 5));
394     // A magnitude in the small range
395     double time3_s = fmod(RAND_DOUBLE, 10);
396     double time3_ms = fmod(RAND_DOUBLE, 10000);
397     double time3_us = fmod(RAND_DOUBLE, 10000000);
398 
399     // Test two precision magnitudes, no decimals.
400     // A magnitude in the high milliseconds.
401     double precision1 = rand() % 250000;
402     // a magnitude in the low microseconds.
403     double precision2 = rand() % 200;
404 
405     process(time1_s, nsRFPService::TimeScale::Seconds, precision1);
406     process(time1_s, nsRFPService::TimeScale::Seconds, precision2);
407     process(time2_s, nsRFPService::TimeScale::Seconds, precision1);
408     process(time2_s, nsRFPService::TimeScale::Seconds, precision2);
409     process(time3_s, nsRFPService::TimeScale::Seconds, precision1);
410     process(time3_s, nsRFPService::TimeScale::Seconds, precision2);
411 
412     process(time1_ms, nsRFPService::TimeScale::MilliSeconds, precision1);
413     process(time1_ms, nsRFPService::TimeScale::MilliSeconds, precision2);
414     process(time2_ms, nsRFPService::TimeScale::MilliSeconds, precision1);
415     process(time2_ms, nsRFPService::TimeScale::MilliSeconds, precision2);
416     process(time3_ms, nsRFPService::TimeScale::MilliSeconds, precision1);
417     process(time3_ms, nsRFPService::TimeScale::MilliSeconds, precision2);
418 
419     process(time1_us, nsRFPService::TimeScale::MicroSeconds, precision1);
420     process(time1_us, nsRFPService::TimeScale::MicroSeconds, precision2);
421     process(time2_us, nsRFPService::TimeScale::MicroSeconds, precision1);
422     process(time2_us, nsRFPService::TimeScale::MicroSeconds, precision2);
423     process(time3_us, nsRFPService::TimeScale::MicroSeconds, precision1);
424     process(time3_us, nsRFPService::TimeScale::MicroSeconds, precision2);
425   }
426   cleanupJitter(jitterEnabled);
427 }
428 
TEST(ResistFingerprinting,ReducePrecision_JitterTestVectors)429 TEST(ResistFingerprinting, ReducePrecision_JitterTestVectors)
430 {
431   bool jitterEnabled = setupJitter(true);
432 
433   // clang-format off
434   /*
435    * Here's our test vector. First we set the secret to the 16 byte value
436    * 0x000102030405060708 0x101112131415161718
437    *
438    * Then we work with a resolution of 500 us which will bucket things as such:
439    *  Per-Clamp Buckets: [0, 500], [500, 1000], ...
440    *  Per-Hash  Buckets: [0, 4000], [4000, 8000], ...
441    *
442    * The first two hash values should be
443    *    0:    SHA-256(0x0001020304050607 || 0x1011121314151617 || 0xa00f000000000000 || 0x0000000000000000)
444    *          78d2d811 804fcaa4 7d472a1e 9fe043d2 dd77b3df 06c1c4f2 9f35f28a e3afbec0
445    *    4000: SHA-256(0x0001020304050607 || 0x1011121314151617 || 0xa00f000000000000 || 0xa00f000000000000)
446    *          1571bf19 92a89cd0 829259d5 b260a4a6 b8da8ad5 2e3ae33c 5571bb8d 8f69cca6
447    *
448    * The midpoints are (if you're doing this manually, you need to correct endian-ness):
449    *   0   : 78d2d811 % 500 = 328
450    *   500 : 804fcaa4 % 500 = 48
451    *   1000: 7d472a1e % 500 = 293
452    *   1500: 9fe043d2 % 500 = 275
453    *   2000: dd77b3df % 500 = 297
454    *   2500: 06c1c4f2 % 500 = 242
455    *   3000: 9f35f28a % 500 = 247
456    *   3500: e3afbec0 % 500 = 339
457    *   4000: 1571bf19 % 500 = 225
458    *   4500: 92a89cd0 % 500 = 198
459    *   5000: 829259d5 % 500 = 218
460    *   5500: b260a4a6 % 500 = 14
461    */
462   // clang-format on
463 
464   // Set the secret
465   long long throwAway;
466   uint8_t hardcodedSecret[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
467                                  0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
468                                  0x14, 0x15, 0x16, 0x17};
469 
470   nsRFPService::RandomMidpoint(0, 500, -1, &throwAway, hardcodedSecret);
471 
472   // Run the test vectors
473   double result;
474 
475   result = nsRFPService::ReduceTimePrecisionImpl(
476       1, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
477       TimerPrecisionType::Normal);
478   ASSERT_EQ(result, 0);
479   result = nsRFPService::ReduceTimePrecisionImpl(
480       327, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
481       TimerPrecisionType::Normal);
482   ASSERT_EQ(result, 0);
483   result = nsRFPService::ReduceTimePrecisionImpl(
484       328, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
485       TimerPrecisionType::Normal);
486   ASSERT_EQ(result, 500);
487   result = nsRFPService::ReduceTimePrecisionImpl(
488       329, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
489       TimerPrecisionType::Normal);
490   ASSERT_EQ(result, 500);
491   result = nsRFPService::ReduceTimePrecisionImpl(
492       499, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
493       TimerPrecisionType::Normal);
494   ASSERT_EQ(result, 500);
495 
496   result = nsRFPService::ReduceTimePrecisionImpl(
497       500, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
498       TimerPrecisionType::Normal);
499   ASSERT_EQ(result, 500);
500   result = nsRFPService::ReduceTimePrecisionImpl(
501       540, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
502       TimerPrecisionType::Normal);
503   ASSERT_EQ(result, 500);
504   result = nsRFPService::ReduceTimePrecisionImpl(
505       547, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
506       TimerPrecisionType::Normal);
507   ASSERT_EQ(result, 500);
508   result = nsRFPService::ReduceTimePrecisionImpl(
509       548, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
510       TimerPrecisionType::Normal);
511   ASSERT_EQ(result, 1000);
512   result = nsRFPService::ReduceTimePrecisionImpl(
513       930, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
514       TimerPrecisionType::Normal);
515   ASSERT_EQ(result, 1000);
516   result = nsRFPService::ReduceTimePrecisionImpl(
517       1255, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
518       TimerPrecisionType::Normal);
519   ASSERT_EQ(result, 1000);
520 
521   result = nsRFPService::ReduceTimePrecisionImpl(
522       4000, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
523       TimerPrecisionType::Normal);
524   ASSERT_EQ(result, 4000);
525   result = nsRFPService::ReduceTimePrecisionImpl(
526       4220, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
527       TimerPrecisionType::Normal);
528   ASSERT_EQ(result, 4000);
529   result = nsRFPService::ReduceTimePrecisionImpl(
530       4224, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
531       TimerPrecisionType::Normal);
532   ASSERT_EQ(result, 4000);
533   result = nsRFPService::ReduceTimePrecisionImpl(
534       4225, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
535       TimerPrecisionType::Normal);
536   ASSERT_EQ(result, 4500);
537   result = nsRFPService::ReduceTimePrecisionImpl(
538       4340, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
539       TimerPrecisionType::Normal);
540   ASSERT_EQ(result, 4500);
541   result = nsRFPService::ReduceTimePrecisionImpl(
542       4499, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
543       TimerPrecisionType::Normal);
544   ASSERT_EQ(result, 4500);
545 
546   result = nsRFPService::ReduceTimePrecisionImpl(
547       4500, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
548       TimerPrecisionType::Normal);
549   ASSERT_EQ(result, 4500);
550   result = nsRFPService::ReduceTimePrecisionImpl(
551       4536, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
552       TimerPrecisionType::Normal);
553   ASSERT_EQ(result, 4500);
554   result = nsRFPService::ReduceTimePrecisionImpl(
555       4695, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
556       TimerPrecisionType::Normal);
557   ASSERT_EQ(result, 4500);
558   result = nsRFPService::ReduceTimePrecisionImpl(
559       4698, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
560       TimerPrecisionType::Normal);
561   ASSERT_EQ(result, 5000);
562   result = nsRFPService::ReduceTimePrecisionImpl(
563       4726, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
564       TimerPrecisionType::Normal);
565   ASSERT_EQ(result, 5000);
566   result = nsRFPService::ReduceTimePrecisionImpl(
567       5106, nsRFPService::TimeScale::MicroSeconds, 500, 4000,
568       TimerPrecisionType::Normal);
569   ASSERT_EQ(result, 5000);
570 
571   cleanupJitter(jitterEnabled);
572 }
573