Example #1
0
        public void Time_TickCalibrationCapacity()
        {
            // Initialize calibration with capacity of 4
            TickCalibration cal      = new TickCalibration(4, 10, 100000);
            double          qpcToHns = 10000000.0 / Platform.Specific.TimeFrequency();

            long ticks = (long)(Platform.Specific.TimeStamp() * qpcToHns);

            // Convert ticks to system file time and verify that it is stable
            long ft = cal.ConvertToFileTime(ticks);

            Assert.AreEqual(ft, cal.ConvertToFileTime(ticks));

            // Add more calibration data until the capacity is reached. After initialization,
            // converter will already have one calibration entry, so these add to it. Note
            // the different adjustment factor (2:1) that will allow us to distinguish this
            // from the previous calibration data.
            cal.AddCalibrationData(ticks + 10, ft + 20);
            cal.AddCalibrationData(ticks + 20, ft + 40);
            cal.AddCalibrationData(ticks + 30, ft + 60);
            Assert.AreEqual(ft + 60, cal.ConvertToFileTime(ticks + 30));
            Assert.AreEqual(ft + 40, cal.ConvertToFileTime(ticks + 20));
            Assert.AreEqual(ft + 20, cal.ConvertToFileTime(ticks + 10));
            Assert.AreEqual(ft, cal.ConvertToFileTime(ticks));

            // This will cause the first calibration point to be removed.
            cal.AddCalibrationData(ticks + 40, ft + 80);
            Assert.AreEqual(ft + 80, cal.ConvertToFileTime(ticks + 40));
            Assert.AreEqual(ft + 60, cal.ConvertToFileTime(ticks + 30));
            Assert.AreEqual(ft + 40, cal.ConvertToFileTime(ticks + 20));
            Assert.AreEqual(ft + 20, cal.ConvertToFileTime(ticks + 10));

            // The following conversion will now be based off the earliest remaining calibration
            // point that was added at (ticks+10, ft+20), which will produce a different result.
            Assert.AreEqual(ft + 10, cal.ConvertToFileTime(ticks));

            // This will cause one more calibration point to be removed.
            cal.AddCalibrationData(ticks + 50, ft + 100);
            Assert.AreEqual(ft + 100, cal.ConvertToFileTime(ticks + 50));
            Assert.AreEqual(ft + 80, cal.ConvertToFileTime(ticks + 40));
            Assert.AreEqual(ft + 60, cal.ConvertToFileTime(ticks + 30));
            Assert.AreEqual(ft + 40, cal.ConvertToFileTime(ticks + 20));

            // The following conversions will now be based off the earliest remaining calibration
            // point that was added at (ticks+20, ft+40), which will produce different results.
            Assert.AreEqual(ft + 30, cal.ConvertToFileTime(ticks + 10));
            Assert.AreEqual(ft + 20, cal.ConvertToFileTime(ticks));

            cal.AddCalibrationData(ticks + 60, ft + 120);
            cal.AddCalibrationData(ticks + 70, ft + 140);
            cal.AddCalibrationData(ticks + 80, ft + 160);
            cal.AddCalibrationData(ticks + 90, ft + 180);
            cal.AddCalibrationData(ticks + 100, ft + 200);
        }
Example #2
0
        public void Time_TickCalibrationMonotonicity()
        {
            TickCalibration cal      = new TickCalibration(256, 10, 100000);
            double          qpcToHns = 10000000.0 / Platform.Specific.TimeFrequency();

            // Converted system times for progressively increasing ticks should also progress
            Assert.IsTrue(cal.ConvertToFileTime(1, false) >= cal.ConvertToFileTime(0, false));
            Assert.IsTrue(cal.ConvertToFileTime(2, false) >= cal.ConvertToFileTime(1, false));
            Assert.IsTrue(cal.ConvertToFileTime(3, false) <= cal.ConvertToFileTime(4, false));
            Assert.IsTrue(cal.ConvertToFileTime(4, false) <= cal.ConvertToFileTime(5, false));

            long ticks = (long)(Platform.Specific.TimeStamp() * qpcToHns);
            long ft    = Platform.Specific.SystemTime();

            // Add new calibration data and verify monotonicity both before and after calibration point
            cal.AddCalibrationData(ticks, ft);
            Assert.IsTrue(cal.ConvertToFileTime(ticks + 1, false) >= cal.ConvertToFileTime(ticks, false));
            Assert.IsTrue(cal.ConvertToFileTime(ticks + 2, false) >= cal.ConvertToFileTime(ticks + 1, false));
            Assert.IsTrue(cal.ConvertToFileTime(ticks - 1, false) <= cal.ConvertToFileTime(ticks, false));
            Assert.IsTrue(cal.ConvertToFileTime(ticks - 2, false) <= cal.ConvertToFileTime(ticks - 1, false));
        }
Example #3
0
        public void Time_TickCalibrationStability()
        {
            TickCalibration cal      = new TickCalibration(256, 10, 100000);
            double          qpcToHns = 10000000.0 / Platform.Specific.TimeFrequency();

            long ft0_0 = cal.ConvertToFileTime(0, false);
            long ft0_1 = cal.ConvertToFileTime(1, false);

            // Multiple consecutive calls should return the same result
            Assert.AreEqual(ft0_0, cal.ConvertToFileTime(0, false));
            Assert.AreEqual(ft0_0, cal.ConvertToFileTime(0, false));
            Assert.AreEqual(ft0_1, cal.ConvertToFileTime(1, false));
            Assert.AreEqual(ft0_1, cal.ConvertToFileTime(1, false));

            long ticks1 = (long)(Platform.Specific.TimeStamp() * qpcToHns);
            long ft1    = Platform.Specific.SystemTime();

            // Add new calibration data and verify stability of previous converted times
            cal.AddCalibrationData(ticks1, ft1);
            Assert.AreEqual(ft0_0, cal.ConvertToFileTime(0, false));
            Assert.AreEqual(ft0_1, cal.ConvertToFileTime(1, false));

            long ticks2 = (long)(Platform.Specific.TimeStamp() * qpcToHns);
            long ft2    = cal.ConvertToFileTime(ticks2, false);
            long ft2_1  = cal.ConvertToFileTime(ticks2 + 1, false);

            // Simulate system clock regressing, recalibrate, then verify stability of previous conversions
            cal.AddCalibrationData(ticks2 + 10, ft2 - 10 * TimeSpan.TicksPerSecond);
            Assert.AreEqual(ft2, cal.ConvertToFileTime(ticks2, false));
            Assert.AreEqual(ft2_1, cal.ConvertToFileTime(ticks2 + 1, false));

            long ticks3 = (long)(Platform.Specific.TimeStamp() * qpcToHns);
            long ft3    = cal.ConvertToFileTime(ticks3, false);
            long ft3_1  = cal.ConvertToFileTime(ticks3 + 1, false);

            // Simulate system clock jumping forward, recalibrate, then verify stability of previous conversions
            cal.AddCalibrationData(ticks3 + 10, ft3 + 10 * TimeSpan.TicksPerSecond);
            Assert.AreEqual(ft3, cal.ConvertToFileTime(ticks3, false));
            Assert.AreEqual(ft3_1, cal.ConvertToFileTime(ticks3 + 1, false));
        }
Example #4
0
        public void Time_TickCalibration()
        {
            TickCalibration cal      = new TickCalibration(256, 10, 100000);
            double          qpcToHns = 10000000.0 / Platform.Specific.TimeFrequency();
            long            ticks0   = (long)(Platform.Specific.TimeStamp() * qpcToHns);
            long            ft0      = Platform.Specific.SystemTime();

            // Calibrate and verify conversions in both directions in time
            cal.AddCalibrationData(ticks0, ft0);
            Assert.AreEqual(ft0, cal.ConvertToFileTime(ticks0, false));
            Assert.AreEqual(ft0 + 1, cal.ConvertToFileTime(ticks0 + 1, false));
            Assert.AreEqual(ft0 + 2, cal.ConvertToFileTime(ticks0 + 2, false));

            // Simulate a system clock advancement with the next calibration point
            long ticks1 = ticks0 + 100;
            long ft1    = ft0 + 200;

            // Calibrate using this new point
            cal.AddCalibrationData(ticks1, ft1);
            Assert.AreEqual(ft1, cal.ConvertToFileTime(ticks1, false));
            Assert.AreEqual(ft1 + 1, cal.ConvertToFileTime(ticks1 + 1, false));
            Assert.AreEqual(ft1 + 2, cal.ConvertToFileTime(ticks1 + 2, false));
            Assert.AreEqual(ft1 - 101, cal.ConvertToFileTime(ticks1 - 1, false));
            Assert.AreEqual(ft1 - 102, cal.ConvertToFileTime(ticks1 - 2, false));

            // Simulate a system clock regression with the next calibration point
            long ticks2 = ticks1 + 100;
            long ft2    = ft1 + 50;

            // Calibrate using this new point
            cal.AddCalibrationData(ticks2, ft2);

            // Ticks prior to ticks2 should use the previous calibration data
            Assert.AreEqual(ft1 + 49, cal.ConvertToFileTime(ticks2 - 51, false));

            // Because the system clock regressed, time conversions for the latter half will be clamped
            // to ft1 + 50 (i.e. ft2) until the tick counter catches up.
            Assert.AreEqual(ft1 + 50, cal.ConvertToFileTime(ticks2 - 50, false));
            Assert.AreEqual(ft1 + 50, cal.ConvertToFileTime(ticks2 - 49, false));
            Assert.AreEqual(ft1 + 50, cal.ConvertToFileTime(ticks2 - 1, false));

            // Ticks from ticks2 onwards should use the latest calibration data
            Assert.AreEqual(ft2, cal.ConvertToFileTime(ticks2, false));
            Assert.AreEqual(ft2 + 1, cal.ConvertToFileTime(ticks2 + 1, false));
            Assert.AreEqual(ft2 + 2, cal.ConvertToFileTime(ticks2 + 2, false));

            // Simulate a system clock jump with the next calibration point
            long ticks3 = ticks2 + 100;
            long ft3    = ft2 + 200;

            // Calibrate using this new point
            cal.AddCalibrationData(ticks3, ft3);

            // Ticks prior to ticks3 should use the previous calibration data
            Assert.AreEqual(ft2 + 99, cal.ConvertToFileTime(ticks3 - 1, false));

            // Ticks from ticks3 onwards use the latest calibration data
            Assert.AreEqual(ft3, cal.ConvertToFileTime(ticks3, false));
            Assert.AreEqual(ft3 + 1, cal.ConvertToFileTime(ticks3 + 1, false));
            Assert.AreEqual(ft3 + 2, cal.ConvertToFileTime(ticks3 + 2, false));
        }