- changed status to closed
Lookup errors in eEPGCache::lookupEventTime()
This bug report assumes that the correct behaviour of the undocumented eEPGCache::lookupEventTime()
parameter direction
on lookup of the EPG data associated with service
is:
direction > 0
return the earliest event that starts after t
.
direction == 0
return the event that spans t
. If t
is spanned by a gap in the EPG, return None.
direction < 0
return the event immediately before the event that spans t
. If t
is spanned by a gap in the EPG, return the event immediately before the gap.
Time-based lookup fails to meet that assumed specification in the following cases:
- If for some event event
event.begin < t && t < event.end
anddirection < 0
,event
is returned, instead of the expected event preceding it. - If for the last event in a service's EPG,
lastEvent.begin < t && t < lastEvent.end
anddirection == 0
,-1
(None
in a Python call) is returned, notlastEvent
. - If for the last event in a service's EPG,
lastEvent.begin < t && t < lastEvent.end
anddirection < 0
,-1
(None
in a Python call) is returned, not the event precedinglastEvent
. - If
t
is after the end of the EPG data,lastEvent.end < t
anddirection == -1
,-1
(None
in a Python call) is returned, notlastEvent
.
Part of the problem is the use of It->second.byTime.lower_bound(t)
when direction <= 0
. using lower_bound(t)
means that depending on the value of t
either the event spanning t
is returned, or the event following it. This complicates the required code, and not all cases appear to be handled correctly.
The code also depends on the behaviour of x--
when x == It->second.byTime.begin()
changing the iterator to x == It->second.byTime.end()
. This is the case in the C++ STL used in the 16.1 Beyonwiz build environment (and also in Ubuntu 16.04), but not in OS X XCode 7.3). The usage also seems counter-intuitive.
I think that eEPGCache::lookupEventTime()
should be re-written to use It->second.byTime.upper_bound(t)
for all values of direction
, and the reliance on the behaviour of x--
when x != It->second.byTime.begin()
should be avoided by testing for x != It->second.byTime.begin()
before decrementing x
.
I have code in test that re-implements eEPGCache::lookupEventTime()
in that way, and also documents the behaviour of direction
.
Replication steps
The problems are not simple to replicate from within the EPG. Call the following Python function from anywhere convenient in the Python code to demonstrate all the above bugs. The parameter serviceref
must be of type eServiceReference
.
def testLookupEventTime(serviceref):
from time import time, ctime
epgCache = eEPGCache.getInstance()
print "testLookupEventTime"
print "testLookupEventTime tests now+5h"
# Find a representative event in the body of the EPG, ~5 hours in the future.
evt = epgCache.lookupEventTime(serviceref, int(time() + 5 * 3600), 0)
if evt:
et = evt.getBeginTime()
# Compare a "direction = -1" lookup when t == event.start
# with a lookup where event.start < t < event.end.
# A lookup with t == event.start and "direction = 0"
# is shown for comparison
evt = epgCache.lookupEventTime(serviceref, et, -1)
print "testLookupEventTime evt now+5h, -1", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
evt = epgCache.lookupEventTime(serviceref, et + 1, -1)
print "testLookupEventTime evt now+5h+1, -1", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
evt = epgCache.lookupEventTime(serviceref, et, 0)
print "testLookupEventTime evt now+5h, 0", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
else:
print "testLookupEventTime tests now+5h - base event not found"
# Find the last event in the service's EPG
epgCache.startTimeQuery(serviceref)
evt = None
evtc = epgCache.getNextTimeEntry()
while evtc:
evt = evtc
evtc = epgCache.getNextTimeEntry()
print "testLookupEventTime"
print "testLookupEventTime tests on last event"
if evt:
et = evt.getBeginTime()
# Compare a "direction = -1" lookup when t == lastEvent.start
# with a lookup where lastEvent.begin < t < lastEvent.end
evt = epgCache.lookupEventTime(serviceref, et, -1)
print "testLookupEventTime evt last et, -1", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
evt = epgCache.lookupEventTime(serviceref, et + 1, -1)
print "testLookupEventTime evt last et+1, -1", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
# Compare a "direction = 0" lookup when t == lastEvent.start
# with a lookup where lastEvent.begin < t < lastEvent.end
evt = epgCache.lookupEventTime(serviceref, et, 0)
print "testLookupEventTime evt last et, 0", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
evt = epgCache.lookupEventTime(serviceref, et + 1, 0)
print "testLookupEventTime evt last et+1, 0", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
else:
print "testLookupEventTime tests on last event - last event not found"
print "testLookupEventTime"
print "testLookupEventTime tests beyond last event"
# lookup for event preceding Fri Jan 15 08:00:00 2027 (should be last eventin the EPG)
evt = epgCache.lookupEventTime(serviceref, 1800000000, -1)
print "testLookupEventTime evt 1800000000, -1", evt and evt.getEventName(), evt and ctime(evt.getBeginTime())
Comments (2)
-
reporter -
reporter - changed status to resolved
Fixed by merge from OpenViX.
- Log in to comment
Fixed in merge from OpenViX