def setUp(self): self.root = SysClock( ) # init before installing mock, so it can do its precision measurement while time still flows self.mockTime = MockTime() self.mockTime.install() self.parent = CorrelatedClock(parentClock=self.root, tickRate=1000) self.altParent = CorrelatedClock(parentClock=self.root, tickRate=50)
def test_speedChangePropagates(self): mockTime = self.mockTime mockTime.timeNow = 5 a = SysClock(tickRate=1000) a1 = CorrelatedClock(a, tickRate=1000, correlation=(50,0)) a2 = CorrelatedClock(a1, tickRate=100, correlation=(28,999)) a3 = CorrelatedClock(a2, tickRate=50, correlation=(5,1003)) a4 = CorrelatedClock(a3, tickRate=25, correlation=(1000,9)) b3 = CorrelatedClock(a2, tickRate=1000, correlation=(500,20)) b4 = CorrelatedClock(b3, tickRate=2000, correlation=(15,90)) at1, a1t1, a2t1, a3t1, a4t1, b3t1, b4t1 = [x.ticks for x in [a,a1,a2,a3,a4,b3,b4]] a3.speed = 0 mockTime.timeNow = 6 # advance time 1 second at2, a1t2, a2t2, a3t2, a4t2, b3t2, b4t2 = [x.ticks for x in [a,a1,a2,a3,a4,b3,b4]] self.assertEquals(at2, at1 + 1000) # a still advances self.assertEquals(a1t2, a1t1 + 1000) # a1 still advances self.assertEquals(a2t2, a2t1 + 100) # a2 still advances self.assertEquals(a3t2, 1003) # a3 is speed zero, is now at the correlation point self.assertEquals(a4t2, 10.5) # a4 is speed zero, a3.ticks is 3 ticks from correlation point for a4, translating to 1.5 ticks from a4 correlation point at its tickRate self.assertEquals(b3t2, b3t1 + 1000) # b3 still advances self.assertEquals(b4t2, b4t1 + 2000) # b4 is paused
def test_distantParentMidHierarchy(self): a = SysClock(tickRate=1000000) a1 = CorrelatedClock(a, tickRate=100, correlation=(50,0)) a2 = CorrelatedClock(a1, tickRate=78, correlation=(28,999)) a3 = CorrelatedClock(a2, tickRate=178, correlation=(5,1003)) a4 = CorrelatedClock(a3, tickRate=28, correlation=(17,9)) self.assertEquals(a3.toOtherClockTicks(a1, 500), a2.toParentTicks(a3.toParentTicks(500)))
def makeTSServerObjects(tsServer, wallClock, timelineSelector, tickRate, startTickValue): """\ create a clock with tick rate, and correlated with wall clock to be paused at the intended start value. create a time line source, that uses the wall clock and timeline clock for creating time stamps to be sent by the TS server on demand of the harness (by calling sendTSMessage). attach that time line to the TS server. No messages are sent over TS protocol until client(s) are connected, and only then when sendTSMessage() is called by the harness """ syncClock = CorrelatedClock(parentClock=wallClock, tickRate=tickRate) syncClock.speed = 0 syncClock.correlation = (wallClock.ticks, startTickValue) pauseSyncTimelineClock(syncClock) # Once added to the TS server, the timeline is available for clients to request via the server # for TS messages from this type of timeline, if it exists for the CI stem sent by the TS client. # normally this CI stem matches a substring of the CII-delivered contentId. syncTimelineSrc = SimpleClockTimelineSource( timelineSelector=timelineSelector, wallClock=wallClock, clock=syncClock) tsServer.attachTimelineSource(syncTimelineSrc) return syncClock
def test_fromParentTicks(self): mockTime = self.mockTime mockTime.timeNow = 1000.0 b = SysClock(tickRate=2000000) c = CorrelatedClock(b, 1000, correlation=(50,300)) self.assertAlmostEqual(c.fromParentTicks(50 + (400-300)*2000), 400, places=5 )
def __init__(self, clock): """\ :param clock: A :class:`~dvbcss.clock.CorrelatedClock` object representing that will be adjusted to match the Wall Clock. """ self.clock = clock self.clock.correlation = clock.correlation.butWith( initialError=float("+inf")) self.tmpClock = CorrelatedClock(self.clock.getParent(), self.clock.tickRate)
def algorithm(self): candidateClock = CorrelatedClock(self.clock.getParent(), tickRate=self.clock.tickRate, correlation=self.clock.correlation) while True: update = False cumulativeOffset = None candidate = (yield self.timeoutSecs) t = self.clock.ticks currentDispersion = self.clock.dispersionAtTime(t) if candidate is not None: candidateClock.correlation = candidate.calcCorrelationFor( self.clock, self.localMaxFreqErrorPpm) candidateDispersion = candidateClock.dispersionAtTime(t) update = candidateDispersion < currentDispersion if update: pt = self.clock.toParentTicks(t) adjustment = candidateClock.fromParentTicks(pt) - t if cumulativeOffset is None: cumulativeOffset = 0 else: cumulativeOffset += adjustment self.clock.correlation = candidateClock.correlation self.onClockAdjusted( self.clock.ticks, adjustment, 1000000000 * currentDispersion, 1000000000 * candidateDispersion, self.clock.correlation.errorGrowthRate) else: pass # update worst dispersion seen so far self.worstDispersion = max(self.worstDispersion, currentDispersion, candidateDispersion) co = cumulativeOffset or 0 # convert None to 0 self.log.info( "Old / New dispersion (millis) is %.5f / %.5f ... offset=%20d new best candidate? %s\n" % (1000 * currentDispersion, 1000 * candidateDispersion, co, str(update))) else: self.log.info("Timeout. Dispersion (millis) is %.5f\n" % (1000 * currentDispersion, )) # retry more quickly if we didn't get an improved candidate if update: time.sleep(self.repeatSecs) else: time.sleep(self.timeoutSecs)
def test_changeCorrelation(self): mockTime = self.mockTime mockTime.timeNow = 5020.8 b = SysClock() c = CorrelatedClock(b, 1000, correlation=(0,300)) self.assertAlmostEqual(c.ticks, 5020.8*1000 + 300, places=5) c.correlation = (50000,320) self.assertEqual(c.correlation, (50000,320)) self.assertAlmostEqual(c.ticks, (int(5020.8*1000000) - 50000) / 1000 + 320, places=5)
def test_changeCorrelation(self): mockTime = self.mockTime b = self.newSysClock() mockTime.timeNow = 5020.8 c = CorrelatedClock(b, 1000, correlation=Correlation(0, 300)) self.assertAlmostEqual(c.ticks, 5020.8 * 1000 + 300, places=5) c.correlation = Correlation(50000, 320) self.assertEqual(c.correlation, Correlation(50000, 320)) self.assertAlmostEqual(c.ticks, (int(5020.8 * 1000000) - 50000) / 1000 + 320, places=5)
def test_dispersionCalcForError(self): """With non-zero error contribution, the dispersion at different times is additional to that of the parent clock, both before and after the correlation time""" a = self.newSysClock(tickRate=1000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0, 0.5, 0.1)) self.assertEquals( a.dispersionAtTime(10) + 0.5 + 0.1 * 10 / 1000, b.dispersionAtTime(10)) self.assertEquals( a.dispersionAtTime(20) + 0.5 + 0.1 * 20 / 1000, b.dispersionAtTime(20)) self.assertEquals( a.dispersionAtTime(-10) + 0.5 + 0.1 * 10 / 1000, b.dispersionAtTime(-10))
def test_changeFreq(self): mockTime = self.mockTime mockTime.timeNow = 5020.8 b = SysClock() c = CorrelatedClock(b, 1000, correlation=(50,300)) self.assertAlmostEqual(c.ticks, (5020.8*1000000 - 50)/(1000000/1000) + 300, places=5) self.assertEqual(c.tickRate, 1000) c.tickRate = 500 self.assertEqual(c.tickRate, 500) self.assertAlmostEqual(c.ticks, (5020.8*1000000 - 50)/(1000000/500) + 300, places=5)
def test_getRoot(self): a = self.newSysClock() b = CorrelatedClock(a, 1000) c = CorrelatedClock(b, 2000) d = CorrelatedClock(c, 3000) self.assertEquals(a.getRoot(), a) self.assertEquals(b.getRoot(), a) self.assertEquals(c.getRoot(), a) self.assertEquals(d.getRoot(), a)
def test_distantParentMidHierarchy(self): a = self.newSysClock(tickRate=1000000) a1 = CorrelatedClock(a, tickRate=100, correlation=Correlation(50, 0)) a2 = CorrelatedClock(a1, tickRate=78, correlation=Correlation(28, 999)) a3 = CorrelatedClock(a2, tickRate=178, correlation=Correlation(5, 1003)) a4 = CorrelatedClock(a3, tickRate=28, correlation=Correlation(17, 9)) self.assertEquals(a3.toOtherClockTicks(a1, 500), a2.toParentTicks(a3.toParentTicks(500)))
def createCSSClientObjects(cmdParser): """\ Create the client objects needed to engage in the CSS-WC and CSS-TS protocols. :param cmdParser the command line parser object """ args = cmdParser.args sysclock=SysClock() wallClock=TunableClock(sysclock,tickRate=1000000000) # nanos # measure precision of wall clock empirically wcPrecisionNanos = measurePrecision(wallClock) * 1000000000 algorithm = LowestDispersionCandidate(wallClock,repeatSecs=0.3,timeoutSecs=0.3) wcClient=WallClockClient(cmdParser.wcBind, args.wcUrl[0], wallClock, algorithm) timelineClock = CorrelatedClock(wallClock, args.timelineClockFrequency) # start recording dispersion of the wall clock dispRecorder=DispersionRecorder(algorithm) dispRecorder.start() print "Connecting, requesting timeline for:" print " Any contentId beginning with:", args.contentIdStem print " and using timeline selector: ", args.timelineSelector print ts = TSClientClockController(args.tsUrl[0], args.contentIdStem, args.timelineSelector, timelineClock, correlationChangeThresholdSecs=0.0) return (ts, timelineClock, args.timelineClockFrequency, wcClient, wallClock, wcPrecisionNanos, dispRecorder)
def threadrun(): # separate thread in which we'll use sleepUntil on a clock that uses tClock as its parent cClock = CorrelatedClock(tClock, tickRate=10, correlation=Correlation(tClock.ticks, 0)) for i in range(0, 10): sleepUntil(cClock, i * 10) print "Tick", cClock.ticks
def test_changeFreq(self): mockTime = self.mockTime b = self.newSysClock() mockTime.timeNow = 5020.8 c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300)) self.assertAlmostEqual(c.ticks, (5020.8 * 1000000 - 50) / (1000000 / 1000) + 300, places=5) self.assertEqual(c.tickRate, 1000) c.tickRate = 500 self.assertEqual(c.tickRate, 500) self.assertAlmostEqual(c.ticks, (5020.8 * 1000000 - 50) / (1000000 / 500) + 300, places=5)
def test_setCorrelationAndSpeed(self): a = self.newSysClock(tickRate=1000000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) b.speed = 1.0 db = MockDependent() b.bind(db) b.setCorrelationAndSpeed(Correlation(5, 0), 2) db.assertNotificationsEqual([b]) self.assertEqual(b.toParentTicks(10), 5005)
def test_setParentNoChangeNoNotify(self): a = self.newSysClock(tickRate=1000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) c = CorrelatedClock(a, 1000, correlation=Correlation(10, 0)) d = MockDependent() b.bind(d) d.assertNotNotified() b.setParent(a) d.assertNotNotified() self.assertEquals(b.getParent(), a)
def test_setParent(self): a = self.newSysClock(tickRate=1000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) c = CorrelatedClock(a, 1000, correlation=Correlation(10, 0)) d = MockDependent() b.bind(d) d.assertNotNotified() b.setParent(c) d.assertNotificationsEqual([b]) self.assertEquals(b.getParent(), c)
def test_differentBranches(self): a = SysClock(tickRate=1000000) a1 = CorrelatedClock(a, tickRate=100, correlation=(50,0)) a2 = CorrelatedClock(a1, tickRate=78, correlation=(28,999)) a3 = CorrelatedClock(a2, tickRate=178, correlation=(5,1003)) a4 = CorrelatedClock(a3, tickRate=28, correlation=(17,9)) b3 = CorrelatedClock(a2, tickRate=1000, correlation=(10,20)) b4 = CorrelatedClock(b3, tickRate=2000, correlation=(15,90)) v = a4.toParentTicks(500) v = a3.toParentTicks(v) v = b3.fromParentTicks(v) v = b4.fromParentTicks(v) self.assertEquals(a4.toOtherClockTicks(b4, 500), v)
def test_ticking(self): mockTime = self.mockTime b = self.newSysClock() mockTime.timeNow = 5020.8 c = CorrelatedClock(b, 1000, correlation=Correlation(0, 300)) self.assertAlmostEqual(c.ticks, 5020.8 * 1000 + 300, places=5) mockTime.timeNow += 22.7 self.assertAlmostEqual(c.ticks, (5020.8 + 22.7) * 1000 + 300, places=5)
def test_changeSpeedeNotifies(self): """Check a change to the correlation propagates notifications to dependents of this clock""" b = self.newSysClock() c = CorrelatedClock(b, 1000, correlation=Correlation(0, 300)) cc = CorrelatedClock(c, 50) d1 = MockDependent() d2 = MockDependent() d3 = MockDependent() b.bind(d1) c.bind(d2) cc.bind(d3) c.speed = 0.5 d1.assertNotNotified() d2.assertNotificationsEqual([c]) d3.assertNotificationsEqual([cc])
def test_quantifyChange(self): a = self.newSysClock() b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) self.assertEquals(float('inf'), b.quantifyChange(Correlation(0, 0), 1.01)) self.assertEquals(1.0, b.quantifyChange(Correlation(0, 1000), 1.0)) b.speed = 0.0 self.assertEquals(0.005, b.quantifyChange(Correlation(0, 5), 0.0))
def test_fromParentTicks(self): mockTime = self.mockTime b = self.newSysClock(tickRate=2000000) mockTime.timeNow = 1000.0 c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300)) self.assertAlmostEqual(c.fromParentTicks(50 + (400 - 300) * 2000), 400, places=5) c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300), speed=0) self.assertEquals(c.fromParentTicks(50), 300) self.assertEquals(c.fromParentTicks(100), 300)
def test_toParentTicks(self): mockTime = self.mockTime b = self.newSysClock(tickRate=2000000) mockTime.timeNow = 1000.0 c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300)) self.assertAlmostEqual(c.toParentTicks(400), 50 + (400 - 300) * 2000, places=5) c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300), speed=0) self.assertEquals(c.toParentTicks(300), 50) self.assertTrue(math.isnan(c.toParentTicks(400)))
def test_changeFreqNotifies(self): mockTime = self.mockTime b = self.newSysClock() mockTime.timeNow = 5020.8 c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300)) cc = CorrelatedClock(c, 50) d1 = MockDependent() d2 = MockDependent() d3 = MockDependent() b.bind(d1) c.bind(d2) cc.bind(d3) c.tickRate = 500 d1.assertNotNotified() d2.assertNotificationsEqual([c]) d3.assertNotificationsEqual([cc])
def test_changeSpeedeNotifies(self): """Check a change to the correlation propagates notifications to dependents of this clock""" b = SysClock() c = CorrelatedClock(b, 1000, correlation=(0,300)) cc = CorrelatedClock(c, 50) d1 = MockDependent() d2 = MockDependent() d3 = MockDependent() b.bind(d1) c.bind(d2) cc.bind(d3) c.speed = 0.5 d1.assertNotNotified() d2.assertNotificationsEqual([c]) d3.assertNotificationsEqual([cc])
def test_changeFreqNotifies(self): mockTime = self.mockTime mockTime.timeNow = 5020.8 b = SysClock() c = CorrelatedClock(b, 1000, correlation=(50,300)) cc = CorrelatedClock(c, 50) d1 = MockDependent() d2 = MockDependent() d3 = MockDependent() b.bind(d1) c.bind(d2) cc.bind(d3) c.tickRate = 500 d1.assertNotNotified() d2.assertNotificationsEqual([c]) d3.assertNotificationsEqual([cc])
class FilterLowestDispersionCandidate(object): """\ Simple filter that will reject a candidate unless its dispersion is lower than that currently being used by the clock. Note that at initialisation, the clock's dispersion is forced to +infinity. """ def __init__(self, clock): """\ :param clock: A :class:`~dvbcss.clock.CorrelatedClock` object representing that will be adjusted to match the Wall Clock. """ self.clock = clock self.clock.correlation = clock.correlation.butWith( initialError=float("+inf")) self.tmpClock = CorrelatedClock(self.clock.getParent(), self.clock.tickRate) def checkCandidate(self, candidate): self.tmpClock.correlation = candidate.calcCorrelationFor(self.clock) t = self.clock.ticks if self.clock.dispersionAtTime(t) > self.tmpClock.dispersionAtTime(t): return True else: return False
def test_differentBranches(self): a = self.newSysClock(tickRate=1000000) a1 = CorrelatedClock(a, tickRate=100, correlation=Correlation(50, 0)) a2 = CorrelatedClock(a1, tickRate=78, correlation=Correlation(28, 999)) a3 = CorrelatedClock(a2, tickRate=178, correlation=Correlation(5, 1003)) a4 = CorrelatedClock(a3, tickRate=28, correlation=Correlation(17, 9)) b3 = CorrelatedClock(a2, tickRate=1000, correlation=Correlation(10, 20)) b4 = CorrelatedClock(b3, tickRate=2000, correlation=Correlation(15, 90)) v = a4.toParentTicks(500) v = a3.toParentTicks(v) v = b3.fromParentTicks(v) v = b4.fromParentTicks(v) self.assertEquals(a4.toOtherClockTicks(b4, 500), v)
def test_getParent(self): b = SysClock() c = CorrelatedClock(b, 1000, correlation=(50,300)) self.assertEqual(c.getParent(), b)
def test_distantParent(self): a = self.newSysClock(tickRate=1000000) a1 = CorrelatedClock(a, tickRate=100, correlation=Correlation(50, 0)) a2 = CorrelatedClock(a1, tickRate=78, correlation=Correlation(28, 999)) self.assertEquals(a2.toOtherClockTicks(a, 500), a1.toParentTicks(a2.toParentTicks(500)))
def test_clockDiff(self): a = self.newSysClock() self.mockTime.timeNow = 1 b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) c = CorrelatedClock(b, 2000, correlation=Correlation(0, 0)) d = CorrelatedClock(c, 3000, correlation=Correlation(0, 0)) e = RangeCorrelatedClock(d, 1000, Correlation(5, 0), Correlation(15005, 5000)) self.assertEquals(float('inf'), b.clockDiff(c)) self.assertEquals(float('inf'), b.clockDiff(d)) self.assertAlmostEquals(0.001666667, b.clockDiff(e), delta=0.000001) self.mockTime.timeNow += 10000000 self.assertEquals(float('inf'), b.clockDiff(c)) self.assertEquals(float('inf'), b.clockDiff(d)) self.assertAlmostEquals(0.001666667, b.clockDiff(e), delta=0.000001) c.tickRate = 1000 self.assertEquals(0, b.clockDiff(c)) c.speed = 1.01 self.assertEquals(float('inf'), b.clockDiff(c))
def test_correlationAndFreqPropertiesInitialised(self): b = self.newSysClock() c = CorrelatedClock(b, 1000, correlation=Correlation(0, 300)) self.assertEqual(c.correlation, Correlation(0, 300)) self.assertEqual(c.tickRate, 1000)
def test_noCommonAncestor(self): a = self.newSysClock() b = self.newSysClock() a1 = CorrelatedClock(a, tickRate=1000, correlation=Correlation(0, 0)) b1 = CorrelatedClock(b, tickRate=1000, correlation=Correlation(0, 0)) a2 = CorrelatedClock(a1, tickRate=1000, correlation=Correlation(0, 0)) b2 = CorrelatedClock(b1, tickRate=1000, correlation=Correlation(0, 0)) self.assertRaises(NoCommonClock, lambda: a.toOtherClockTicks(b, 5)) self.assertRaises(NoCommonClock, lambda: a.toOtherClockTicks(b1, 5)) self.assertRaises(NoCommonClock, lambda: a.toOtherClockTicks(b2, 5)) self.assertRaises(NoCommonClock, lambda: a1.toOtherClockTicks(b, 5)) self.assertRaises(NoCommonClock, lambda: a1.toOtherClockTicks(b1, 5)) self.assertRaises(NoCommonClock, lambda: a1.toOtherClockTicks(b2, 5)) self.assertRaises(NoCommonClock, lambda: a2.toOtherClockTicks(b, 5)) self.assertRaises(NoCommonClock, lambda: a2.toOtherClockTicks(b1, 5)) self.assertRaises(NoCommonClock, lambda: a2.toOtherClockTicks(b2, 5)) self.assertRaises(NoCommonClock, lambda: b.toOtherClockTicks(a, 5)) self.assertRaises(NoCommonClock, lambda: b.toOtherClockTicks(a1, 5)) self.assertRaises(NoCommonClock, lambda: b.toOtherClockTicks(a2, 5)) self.assertRaises(NoCommonClock, lambda: b1.toOtherClockTicks(a, 5)) self.assertRaises(NoCommonClock, lambda: b1.toOtherClockTicks(a1, 5)) self.assertRaises(NoCommonClock, lambda: b1.toOtherClockTicks(a2, 5)) self.assertRaises(NoCommonClock, lambda: b2.toOtherClockTicks(a, 5)) self.assertRaises(NoCommonClock, lambda: b2.toOtherClockTicks(a1, 5)) self.assertRaises(NoCommonClock, lambda: b2.toOtherClockTicks(a2, 5))
def test_rebase(self): b = SysClock(tickRate=1000) c = CorrelatedClock(b, 1000, correlation=(50,300)) c.rebaseCorrelationAtTicks(400) self.assertEquals(c.correlation, (150,400))
class Test_OffsetClock(unittest.TestCase): """\ Tests for OffsetClock """ def setUp(self): self.root = SysClock( ) # init before installing mock, so it can do its precision measurement while time still flows self.mockTime = MockTime() self.mockTime.install() self.parent = CorrelatedClock(parentClock=self.root, tickRate=1000) self.altParent = CorrelatedClock(parentClock=self.root, tickRate=50) def tearDown(self): self.mockTime.uninstall() def test_speedAlways1(self): oc = OffsetClock(parentClock=self.parent) self.assertEquals(oc.speed, 1) self.parent.speed = 2.7 self.assertEquals(oc.speed, 1) def test_effectiveSpeedSameAsParents(self): oc = OffsetClock(parentClock=self.parent) self.assertEquals(oc.getEffectiveSpeed(), self.parent.getEffectiveSpeed()) self.parent.speed = 2.7 self.assertEquals(oc.getEffectiveSpeed(), self.parent.getEffectiveSpeed()) def test_inheritsTickRateFromParent(self): oc = OffsetClock(parentClock=self.parent) self.assertEquals(oc.tickRate, self.parent.tickRate) self.parent.tickRate = 25 self.assertEquals(oc.tickRate, self.parent.tickRate) def test_offsetAppliedAtSpeed1(self): OC_AHEAD_BY = 0.050 oc = OffsetClock(parentClock=self.parent, offset=OC_AHEAD_BY) self.parent.speed = 1 t = oc.ticks # advance time and see if OffsetClock was indeed ahead by OC_AHEAD_BY seconds self.mockTime.timeNow = self.mockTime.timeNow + OC_AHEAD_BY t2 = self.parent.ticks self.assertEquals(t, t2) def test_offsetAppliedAtSpeed0(self): OC_AHEAD_BY = 0.098 oc = OffsetClock(parentClock=self.parent, offset=OC_AHEAD_BY) self.parent.speed = 0 t = oc.ticks # advance time and see if OffsetClock was indeed ahead by OC_AHEAD_BY seconds self.mockTime.timeNow = self.mockTime.timeNow + OC_AHEAD_BY t2 = self.parent.ticks self.assertEquals(t, t2) def test_offsetAppliedAtSpeedGreaterThan1(self): OC_AHEAD_BY = 0.02 oc = OffsetClock(parentClock=self.parent, offset=OC_AHEAD_BY) self.parent.speed = 2 t = oc.ticks # advance time and see if OffsetClock was indeed ahead by OC_AHEAD_BY seconds self.mockTime.timeNow = self.mockTime.timeNow + OC_AHEAD_BY t2 = self.parent.ticks self.assertEquals(t, t2) def test_noOffsetWorks(self): oc = OffsetClock(parentClock=self.parent, offset=0) self.assertEquals(oc.ticks, self.parent.ticks) def test_offsetChangeNewOffsetUsed(self): oc = OffsetClock(parentClock=self.parent, offset=0.040) self.assertEquals(oc.ticks, self.parent.ticks + 40) oc.offset = 0.065 self.assertEquals(oc.ticks, self.parent.ticks + 65) def test_parentChangedOffsetStillApplied(self): oc = OffsetClock(parentClock=self.parent, offset=0.040) self.assertEquals(oc.getParent(), self.parent) self.assertEquals(oc.ticks, self.parent.ticks + 40) oc.setParent(self.altParent) self.assertEquals(oc.getParent(), self.altParent) self.assertEquals(oc.ticks, self.altParent.ticks + 2) def test_parentChangeCausesNotification(self): oc = OffsetClock(parentClock=self.parent, offset=0.040) dep = MockDependent() oc.bind(dep) dep.assertNotNotified() oc.setParent(self.altParent) dep.assertNotificationsEqual([oc]) def test_negativeOffsetWorks(self): OC_BEHIND_BY = 0.050 oc = OffsetClock(parentClock=self.parent, offset=-OC_BEHIND_BY) self.parent.speed = 1 t = oc.ticks # regress time and see if OffsetClock was indeed behind by OC_BEHIND_BY seconds self.mockTime.timeNow = self.mockTime.timeNow - OC_BEHIND_BY t2 = self.parent.ticks self.assertEquals(t, t2) def test_toRootTicks(self): OC_AHEAD_BY = 0.124 oc = OffsetClock(parentClock=self.parent, offset=OC_AHEAD_BY) t = 1285.2 rt = oc.toRootTicks(t) rt2 = self.parent.toRootTicks(t) self.assertEquals(rt + OC_AHEAD_BY * self.root.tickRate, rt2) def test_fromRootTicks(self): OC_AHEAD_BY = 0.124 oc = OffsetClock(parentClock=self.parent, offset=OC_AHEAD_BY) rt = 22849128 t = oc.fromRootTicks(rt) t2 = self.parent.fromRootTicks(rt + OC_AHEAD_BY * self.root.tickRate) self.assertEquals(t, t2)
def test_dispersionCalcForZeroError(self): """With zero error contribution, the dispersion at different times is the same as for the parent clock""" a = self.newSysClock(tickRate=1000) b = CorrelatedClock(a, 1000, correlation=Correlation(0, 0)) self.assertEquals(a.dispersionAtTime(10), b.dispersionAtTime(10)) self.assertEquals(a.dispersionAtTime(20), b.dispersionAtTime(20))
def test_distantParent(self): a = SysClock(tickRate=1000000) a1 = CorrelatedClock(a, tickRate=100, correlation=(50,0)) a2 = CorrelatedClock(a1, tickRate=78, correlation=(28,999)) self.assertEquals(a2.toOtherClockTicks(a, 500), a1.toParentTicks(a2.toParentTicks(500)))
def test_noCommonAncestor(self): a = SysClock() b = SysClock() a1 = CorrelatedClock(a, tickRate=1000, correlation=(0,0)) b1 = CorrelatedClock(b, tickRate=1000, correlation=(0,0)) a2 = CorrelatedClock(a1, tickRate=1000, correlation=(0,0)) b2 = CorrelatedClock(b1, tickRate=1000, correlation=(0,0)) self.assertRaises(NoCommonClock, lambda:a.toOtherClockTicks(b, 5)) self.assertRaises(NoCommonClock, lambda:a.toOtherClockTicks(b1, 5)) self.assertRaises(NoCommonClock, lambda:a.toOtherClockTicks(b2, 5)) self.assertRaises(NoCommonClock, lambda:a1.toOtherClockTicks(b, 5)) self.assertRaises(NoCommonClock, lambda:a1.toOtherClockTicks(b1, 5)) self.assertRaises(NoCommonClock, lambda:a1.toOtherClockTicks(b2, 5)) self.assertRaises(NoCommonClock, lambda:a2.toOtherClockTicks(b, 5)) self.assertRaises(NoCommonClock, lambda:a2.toOtherClockTicks(b1, 5)) self.assertRaises(NoCommonClock, lambda:a2.toOtherClockTicks(b2, 5)) self.assertRaises(NoCommonClock, lambda:b.toOtherClockTicks(a, 5)) self.assertRaises(NoCommonClock, lambda:b.toOtherClockTicks(a1, 5)) self.assertRaises(NoCommonClock, lambda:b.toOtherClockTicks(a2, 5)) self.assertRaises(NoCommonClock, lambda:b1.toOtherClockTicks(a, 5)) self.assertRaises(NoCommonClock, lambda:b1.toOtherClockTicks(a1, 5)) self.assertRaises(NoCommonClock, lambda:b1.toOtherClockTicks(a2, 5)) self.assertRaises(NoCommonClock, lambda:b2.toOtherClockTicks(a, 5)) self.assertRaises(NoCommonClock, lambda:b2.toOtherClockTicks(a1, 5)) self.assertRaises(NoCommonClock, lambda:b2.toOtherClockTicks(a2, 5))
def test_rebase(self): b = self.newSysClock(tickRate=1000) c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300)) c.rebaseCorrelationAtTicks(400) self.assertEquals(c.correlation, Correlation(150, 400))
def test_getParent(self): b = self.newSysClock() c = CorrelatedClock(b, 1000, correlation=Correlation(50, 300)) self.assertEqual(c.getParent(), b)