From bf28325b6126ca0feec5c12433263d666514ba93 Mon Sep 17 00:00:00 2001 From: William Elwood Date: Fri, 1 Nov 2019 10:15:10 +0000 Subject: [PATCH] Enable tests for expired cache If the cache is expired but then all downloads fail, the cache should be used. --- dnscrypt-proxy/sources.go | 29 ++++++++++++----------------- dnscrypt-proxy/sources_test.go | 4 ++-- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/dnscrypt-proxy/sources.go b/dnscrypt-proxy/sources.go index 73138519..8be99adf 100644 --- a/dnscrypt-proxy/sources.go +++ b/dnscrypt-proxy/sources.go @@ -52,7 +52,7 @@ func (source *Source) checkSignature(bin, sig []byte) (err error) { // timeNow can be replaced by tests to provide a static value var timeNow = time.Now -func (source *Source) fetchFromCache() (delay time.Duration, err error) { +func (source *Source) fetchFromCache(now time.Time) (delay time.Duration, err error) { var bin, sig []byte if bin, err = ioutil.ReadFile(source.cacheFile); err != nil { return @@ -68,7 +68,7 @@ func (source *Source) fetchFromCache() (delay time.Duration, err error) { if fi, err = os.Stat(source.cacheFile); err != nil { return } - if elapsed := timeNow().Sub(fi.ModTime()); elapsed < source.cacheTTL { + if elapsed := now.Sub(fi.ModTime()); elapsed < source.cacheTTL { delay = source.prefetchDelay - elapsed dlog.Debugf("Source [%s] cache file [%s] is still fresh, next update: %v", source.name, source.cacheFile, delay) } else { @@ -105,15 +105,20 @@ func fetchFromURL(xTransport *XTransport, u *url.URL) (bin []byte, err error) { return } -func (source *Source) fetchWithCache(xTransport *XTransport) (delay time.Duration, err error) { - if delay, err = source.fetchFromCache(); err != nil { +func (source *Source) fetchWithCache(xTransport *XTransport, now time.Time) (delay time.Duration, err error) { + if delay, err = source.fetchFromCache(now); err != nil { if len(source.urls) == 0 { dlog.Errorf("Source [%s] cache file [%s] not present and no URL given", source.name, source.cacheFile) return } dlog.Debugf("Source [%s] cache file [%s] not present", source.name, source.cacheFile) } - if delay > 0 { + if len(source.urls) > 0 { + defer func() { + source.refresh = now.Add(delay) + }() + } + if len(source.urls) == 0 || delay > 0 { return } delay = MinimumPrefetchInterval @@ -166,16 +171,7 @@ func NewSource(name string, xTransport *XTransport, urls []string, minisignKeySt } else { return source, err } - now := timeNow() - - var delay time.Duration - if len(urls) <= 0 { - delay, err = source.fetchWithCache(xTransport) - } else { - delay, err = source.fetchWithCache(xTransport) - source.refresh = now.Add(delay) - } - if err != nil { + if _, err = source.fetchWithCache(xTransport, timeNow()); err != nil { return } dlog.Noticef("Source [%s] loaded", name) @@ -191,11 +187,10 @@ func PrefetchSources(xTransport *XTransport, sources []*Source) time.Duration { continue } dlog.Debugf("Prefetching [%s]", source.name) - if delay, err := source.fetchWithCache(xTransport); err != nil { + if delay, err := source.fetchWithCache(xTransport, now); err != nil { dlog.Debugf("Prefetching [%s] failed: %v", source.name, err) } else { dlog.Debugf("Prefetching [%s] succeeded, next update: %v", source.name, delay) - source.refresh = now.Add(delay) if delay >= MinimumPrefetchInterval && (interval == MinimumPrefetchInterval || interval > delay) { interval = delay } diff --git a/dnscrypt-proxy/sources_test.go b/dnscrypt-proxy/sources_test.go index 8d8c89f1..e57893a7 100644 --- a/dnscrypt-proxy/sources_test.go +++ b/dnscrypt-proxy/sources_test.go @@ -194,8 +194,8 @@ func checkTestServer(c *check.C, d *SourceTestData) { func setupSourceTest(t *testing.T) (func(), *SourceTestData) { d := &SourceTestData{n: -1, xTransport: NewXTransport()} d.cacheTests = map[string]SourceTestState{ // determines cache files written to disk before each call - "correct": TestStateCorrect, - //"expired": TestStateExpired, // TODO: an expired cache should be used if no download passes signature verification + "correct": TestStateCorrect, + "expired": TestStateExpired, "partial": TestStatePartial, "partial-sig": TestStatePartialSig, "missing": TestStateMissing,