commit:     896802def8a7c3fc495cfd3c534bf773f1e17af7
Author:     Rahil Bhimjiani <me <AT> rahil <DOT> rocks>
AuthorDate: Thu Mar 13 07:37:55 2025 +0000
Commit:     Rahil Bhimjiani <rahil3108 <AT> gmail <DOT> com>
CommitDate: Thu Mar 13 07:38:33 2025 +0000
URL:        https://gitweb.gentoo.org/repo/proj/guru.git/commit/?id=896802de

net-dns/blocky: remove 0.22

Signed-off-by: Rahil Bhimjiani <me <AT> rahil.rocks>

 net-dns/blocky/Manifest                            |    3 -
 net-dns/blocky/blocky-0.22.ebuild                  |  104 -
 .../blocky/files/disable-failed-tests-0.22.patch   | 2272 --------------------
 3 files changed, 2379 deletions(-)

diff --git a/net-dns/blocky/Manifest b/net-dns/blocky/Manifest
index 7ad31430d..3bac1ddd7 100644
--- a/net-dns/blocky/Manifest
+++ b/net-dns/blocky/Manifest
@@ -1,6 +1,3 @@
-DIST blocky-0.22-deps.tar.xz 163869124 BLAKE2B 
e98614feaeb11604866d08003147871096c993cdb90c85bba46ea999a339570ca1500a80bddee202595372ec5d22baa6ec0345d8cf50ffee6d61dd8d6495d49f
 SHA512 
883e5dd66cf974c6d8c73a94c7677d5003ceb7a3ba68001c2d9d36e1e4d1ea64f0818d30240fe77f192ad3f95ede93127bed9adc9647da07a9b9bebc958ffd33
-DIST blocky-0.22-docs.tar.gz 5639822 BLAKE2B 
e177790deb7493f84d8217661e4e4296004a9db7e00ff8d37dbd3c4ed8b7ba0a7cf431067c103f25784e46ca7a8bf80532cdd8f305f3e4ce119890027f0eb186
 SHA512 
3eed0ff726479826fbefb4140c36bb26825124134d1fbbecf74a31b2fbdde993630adc645ea2e582ce8d415736cc85b20f64a835c87da98700b715c03d368e75
-DIST blocky-0.22.tar.gz 712644 BLAKE2B 
d74881026421337a0fc32a6af2cf6bff736e0130ac599cd80714f0cafff1e81864e0327bc773f8377106421642cf545b76407fca94f07425c428ff8512a7113b
 SHA512 
928ba882cb567f80b9b00c1ab74ba2fba0324b9e5fb6439789d50d8fd438a26f84772d36f91ef9c3a2351c798a399c15aa1b69927a2da11795edd576b7bae6a4
 DIST blocky-0.23-deps.tar.xz 191529448 BLAKE2B 
fbad27f70b73832e0862b32267be0e9956c39c570f4e8d16be6a1b7eaa8ea779df52d1da533486d2b0d3e5b163602b62283ac006de4adc0861ec208fd9f50bd8
 SHA512 
89441e8082260b7c8a850b91029540554fc8af4bdba1996adb07ff57781c0e92ee439b915cd1473d16fba9bd31612b6c267c2fe6f96096a4f9ed4fa23d46165d
 DIST blocky-0.23-docs.tar.gz 6773940 BLAKE2B 
8114e49c8c8b7c01a1376dd0ef15b5eee966fc18c84d8645aa91c3524876167de810a17d63f2e287a3fe4c56906076783e135cf0c209886870588f40190e9d78
 SHA512 
aec00c88ea97f7f2d145020e666f77f992b53cd8867d4d4c5bc5a094b06889c35d7019d0e491fe02fb1dd803912613ec7f874f4d7a9f0d06e41c7bb8c609d956
 DIST blocky-0.23.tar.gz 7236537 BLAKE2B 
4dd8b4a9587ed2b768ff2cf8809e14242032d7e8be3d3c422eb5518df33c32c0f767ba8e7490f353e81ede8c150cf3175621ea35ad3aa682f62c7d169c511b63
 SHA512 
22431da4c2f259411b7eb790e8f05a7264d0aa96fe4774722bbe71cf9459a3ed7f434b4b295c95b80f2efc6de55ff645f860443838fe793bc413d74b77e395be

diff --git a/net-dns/blocky/blocky-0.22.ebuild 
b/net-dns/blocky/blocky-0.22.ebuild
deleted file mode 100644
index 5b601c882..000000000
--- a/net-dns/blocky/blocky-0.22.ebuild
+++ /dev/null
@@ -1,104 +0,0 @@
-# Copyright 1999-2024 Gentoo Authors
-# Distributed under the terms of the GNU General Public License v2
-
-EAPI=8
-
-inherit fcaps go-module systemd shell-completion
-
-DESCRIPTION="Fast and lightweight DNS proxy as ad-blocker with many features 
written in Go"
-HOMEPAGE="https://github.com/0xERR0R/blocky/";
-
-DOCUMENTATION_COMMIT=9c6a86eb163e758686c5d6d4d5259deb086a8aa9
-
-if [[ ${PV} == 9999* ]]; then
-       inherit git-r3
-       EGIT_REPO_URI="https://github.com/0xERR0R/blocky.git";
-else
-       SRC_URI="
-       https://github.com/0xERR0R/blocky/archive/v${PV}.tar.gz -> ${P}.tar.gz
-       
https://github.com/rahilarious/gentoo-distfiles/releases/download/${P}/deps.tar.xz
 -> ${P}-deps.tar.xz
-       doc? ( 
https://github.com/0xERR0R/blocky/archive/${DOCUMENTATION_COMMIT}.tar.gz -> 
${P}-docs.tar.gz )
-"
-       KEYWORDS="~amd64"
-fi
-
-# main
-LICENSE="Apache-2.0"
-# deps
-LICENSE+=" AGPL-3 BSD-2 BSD ISC MIT MPL-2.0"
-SLOT="0"
-IUSE="doc"
-
-# RESTRICT="test"
-
-RDEPEND="
-       acct-user/blocky
-       acct-group/blocky
-"
-
-PATCHES=(
-       "${FILESDIR}"/disable-failed-tests-0.22.patch
-)
-
-FILECAPS=(
-       -m 755 'cap_net_bind_service=+ep' usr/bin/"${PN}"
-)
-
-src_unpack() {
-       if [[ ${PV} == 9999* ]]; then
-               git-r3_src_unpack
-               go-module_live_vendor
-               if use doc; then
-                       EGIT_BRANCH="gh-pages"
-                       EGIT_CHECKOUT_DIR="${WORKDIR}/${P}-doc"
-                       git-r3_src_unpack
-               fi
-       else
-               go-module_src_unpack
-       fi
-}
-
-src_compile() {
-       [[ ${PV} != 9999* ]] && export VERSION="${PV}"
-
-       # mimicking project's Dockerfile
-       emake GO_SKIP_GENERATE=yes GO_BUILD_FLAGS="-tags static -v " build
-
-       local shell
-       for shell in bash fish zsh; do
-               bin/"${PN}" completion "${shell}" > "${PN}"."${shell}" || die
-       done
-}
-
-src_test() {
-       # mimcking make test
-       ego run github.com/onsi/ginkgo/v2/ginkgo --label-filter="!e2e" 
--coverprofile=coverage.txt --covermode=atomic --cover -r -p
-       ego tool cover -html coverage.txt -o coverage.html
-}
-
-src_install() {
-       # primary program
-       dobin bin/"${PN}"
-
-       # secondary supplements
-       insinto /etc/"${PN}"
-       newins docs/config.yml config.yml.sample
-
-       newbashcomp "${PN}".bash "${PN}"
-       dofishcomp "${PN}".fish
-       newzshcomp "${PN}".zsh _"${PN}"
-
-       # TODO openrc services
-       systemd_newunit "${FILESDIR}"/blocky-0.22.service "${PN}".service
-
-       # docs
-       einstalldocs
-
-       if use doc; then
-               if [[ ${PV} == 9999* ]]; then
-                       dodoc -r ../"${P}"-doc/main/*
-               else
-                       dodoc -r ../"${PN}"-"${DOCUMENTATION_COMMIT}"/v"${PV}"/*
-               fi
-       fi
-}

diff --git a/net-dns/blocky/files/disable-failed-tests-0.22.patch 
b/net-dns/blocky/files/disable-failed-tests-0.22.patch
deleted file mode 100644
index 98883469d..000000000
--- a/net-dns/blocky/files/disable-failed-tests-0.22.patch
+++ /dev/null
@@ -1,2272 +0,0 @@
-diff --git a/cache/stringcache/chained_grouped_cache_test.go 
b/cache/stringcache/chained_grouped_cache_test.go
-deleted file mode 100644
-index e83f956..0000000
---- a/cache/stringcache/chained_grouped_cache_test.go
-+++ /dev/null
-@@ -1,93 +0,0 @@
--package stringcache_test
--
--import (
--      "github.com/0xERR0R/blocky/cache/stringcache"
--      . "github.com/onsi/ginkgo/v2"
--      . "github.com/onsi/gomega"
--)
--
--var _ = Describe("Chained grouped cache", func() {
--      Describe("Empty cache", func() {
--              When("empty cache was created", func() {
--                      cache := stringcache.NewChainedGroupedCache()
--
--                      It("should have element count of 0", func() {
--                              
Expect(cache.ElementCount("someGroup")).Should(BeNumerically("==", 0))
--                      })
--
--                      It("should not find any string", func() {
--                              Expect(cache.Contains("searchString", 
[]string{"someGroup"})).Should(BeEmpty())
--                      })
--              })
--      })
--      Describe("Delegation", func() {
--              When("Chained cache contains delegates", func() {
--                      inMemoryCache1 := 
stringcache.NewInMemoryGroupedStringCache()
--                      inMemoryCache2 := 
stringcache.NewInMemoryGroupedStringCache()
--                      cache := 
stringcache.NewChainedGroupedCache(inMemoryCache1, inMemoryCache2)
--
--                      factory := cache.Refresh("group1")
--
--                      factory.AddEntry("string1")
--                      factory.AddEntry("string2")
--
--                      It("cache should still have 0 element, since finish was 
not executed", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 0))
--                      })
--
--                      It("factory has 4 elements (both caches)", func() {
--                              
Expect(factory.Count()).Should(BeNumerically("==", 4))
--                      })
--
--                      It("should have element count of 4", func() {
--                              factory.Finish()
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 4))
--                      })
--
--                      It("should find strings", func() {
--                              Expect(cache.Contains("string1", 
[]string{"group1"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("string2", 
[]string{"group1", "someOtherGroup"})).Should(ConsistOf("group1"))
--                      })
--              })
--      })
--
--      Describe("Cache refresh", func() {
--              When("cache with 2 groups was created", func() {
--                      inMemoryCache1 := 
stringcache.NewInMemoryGroupedStringCache()
--                      inMemoryCache2 := 
stringcache.NewInMemoryGroupedStringCache()
--                      cache := 
stringcache.NewChainedGroupedCache(inMemoryCache1, inMemoryCache2)
--
--                      factory := cache.Refresh("group1")
--
--                      factory.AddEntry("g1")
--                      factory.AddEntry("both")
--                      factory.Finish()
--
--                      factory = cache.Refresh("group2")
--                      factory.AddEntry("g2")
--                      factory.AddEntry("both")
--                      factory.Finish()
--
--                      It("should contain 4 elements in 2 groups", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 4))
--                              
Expect(cache.ElementCount("group2")).Should(BeNumerically("==", 4))
--                              Expect(cache.Contains("g1", []string{"group1", 
"group2"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("g2", []string{"group1", 
"group2"})).Should(ConsistOf("group2"))
--                              Expect(cache.Contains("both", 
[]string{"group1", "group2"})).Should(ConsistOf("group1", "group2"))
--                      })
--
--                      It("Should replace group content on refresh", func() {
--                              factory := cache.Refresh("group1")
--                              factory.AddEntry("newString")
--                              factory.Finish()
--
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 2))
--                              
Expect(cache.ElementCount("group2")).Should(BeNumerically("==", 4))
--                              Expect(cache.Contains("g1", []string{"group1", 
"group2"})).Should(BeEmpty())
--                              Expect(cache.Contains("newString", 
[]string{"group1", "group2"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("g2", []string{"group1", 
"group2"})).Should(ConsistOf("group2"))
--                              Expect(cache.Contains("both", 
[]string{"group1", "group2"})).Should(ConsistOf("group2"))
--                      })
--              })
--      })
--})
-diff --git a/cache/stringcache/in_memory_grouped_cache_test.go 
b/cache/stringcache/in_memory_grouped_cache_test.go
-deleted file mode 100644
-index 7692935..0000000
---- a/cache/stringcache/in_memory_grouped_cache_test.go
-+++ /dev/null
-@@ -1,130 +0,0 @@
--package stringcache_test
--
--import (
--      "github.com/0xERR0R/blocky/cache/stringcache"
--      . "github.com/onsi/ginkgo/v2"
--      . "github.com/onsi/gomega"
--)
--
--var _ = Describe("In-Memory grouped cache", func() {
--      Describe("Empty cache", func() {
--              When("empty cache was created", func() {
--                      cache := stringcache.NewInMemoryGroupedStringCache()
--
--                      It("should have element count of 0", func() {
--                              
Expect(cache.ElementCount("someGroup")).Should(BeNumerically("==", 0))
--                      })
--
--                      It("should not find any string", func() {
--                              Expect(cache.Contains("searchString", 
[]string{"someGroup"})).Should(BeEmpty())
--                      })
--              })
--              When("cache with one empty group", func() {
--                      cache := stringcache.NewInMemoryGroupedStringCache()
--                      factory := cache.Refresh("group1")
--                      factory.Finish()
--
--                      It("should have element count of 0", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 0))
--                      })
--
--                      It("should not find any string", func() {
--                              Expect(cache.Contains("searchString", 
[]string{"group1"})).Should(BeEmpty())
--                      })
--              })
--      })
--      Describe("Cache creation", func() {
--              When("cache with 1 group was created", func() {
--                      cache := stringcache.NewInMemoryGroupedStringCache()
--
--                      factory := cache.Refresh("group1")
--
--                      factory.AddEntry("string1")
--                      factory.AddEntry("string2")
--
--                      It("cache should still have 0 element, since finish was 
not executed", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 0))
--                      })
--
--                      It("factory has 2 elements", func() {
--                              
Expect(factory.Count()).Should(BeNumerically("==", 2))
--                      })
--
--                      It("should have element count of 2", func() {
--                              factory.Finish()
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 2))
--                      })
--
--                      It("should find strings", func() {
--                              Expect(cache.Contains("string1", 
[]string{"group1"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("string2", 
[]string{"group1", "someOtherGroup"})).Should(ConsistOf("group1"))
--                      })
--              })
--              When("String grouped cache is used", func() {
--                      cache := stringcache.NewInMemoryGroupedStringCache()
--                      factory := cache.Refresh("group1")
--
--                      factory.AddEntry("string1")
--                      factory.AddEntry("/string2/")
--                      factory.Finish()
--
--                      It("should ignore regex", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 1))
--                              Expect(cache.Contains("string1", 
[]string{"group1"})).Should(ConsistOf("group1"))
--                      })
--              })
--              When("Regex grouped cache is used", func() {
--                      cache := stringcache.NewInMemoryGroupedRegexCache()
--                      factory := cache.Refresh("group1")
--
--                      factory.AddEntry("string1")
--                      factory.AddEntry("/string2/")
--                      factory.Finish()
--
--                      It("should ignore non-regex", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 1))
--                              Expect(cache.Contains("string1", 
[]string{"group1"})).Should(BeEmpty())
--                              Expect(cache.Contains("string2", 
[]string{"group1"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("shouldalsomatchstring2", 
[]string{"group1"})).Should(ConsistOf("group1"))
--                      })
--              })
--      })
--
--      Describe("Cache refresh", func() {
--              When("cache with 2 groups was created", func() {
--                      cache := stringcache.NewInMemoryGroupedStringCache()
--
--                      factory := cache.Refresh("group1")
--
--                      factory.AddEntry("g1")
--                      factory.AddEntry("both")
--                      factory.Finish()
--
--                      factory = cache.Refresh("group2")
--                      factory.AddEntry("g2")
--                      factory.AddEntry("both")
--                      factory.Finish()
--
--                      It("should contain 4 elements in 2 groups", func() {
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 2))
--                              
Expect(cache.ElementCount("group2")).Should(BeNumerically("==", 2))
--                              Expect(cache.Contains("g1", []string{"group1", 
"group2"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("g2", []string{"group1", 
"group2"})).Should(ConsistOf("group2"))
--                              Expect(cache.Contains("both", 
[]string{"group1", "group2"})).Should(ConsistOf("group1", "group2"))
--                      })
--
--                      It("Should replace group content on refresh", func() {
--                              factory := cache.Refresh("group1")
--                              factory.AddEntry("newString")
--                              factory.Finish()
--
--                              
Expect(cache.ElementCount("group1")).Should(BeNumerically("==", 1))
--                              
Expect(cache.ElementCount("group2")).Should(BeNumerically("==", 2))
--                              Expect(cache.Contains("g1", []string{"group1", 
"group2"})).Should(BeEmpty())
--                              Expect(cache.Contains("newString", 
[]string{"group1", "group2"})).Should(ConsistOf("group1"))
--                              Expect(cache.Contains("g2", []string{"group1", 
"group2"})).Should(ConsistOf("group2"))
--                              Expect(cache.Contains("both", 
[]string{"group1", "group2"})).Should(ConsistOf("group2"))
--                      })
--              })
--      })
--})
-diff --git a/lists/downloader_test.go b/lists/downloader_test.go
-deleted file mode 100644
-index 5387c86..0000000
---- a/lists/downloader_test.go
-+++ /dev/null
-@@ -1,218 +0,0 @@
--package lists
--
--import (
--      "errors"
--      "io"
--      "net"
--      "net/http"
--      "net/http/httptest"
--      "strings"
--      "sync/atomic"
--      "time"
--
--      "github.com/0xERR0R/blocky/config"
--      . "github.com/0xERR0R/blocky/evt"
--      . "github.com/0xERR0R/blocky/helpertest"
--      "github.com/0xERR0R/blocky/log"
--      . "github.com/onsi/ginkgo/v2"
--      . "github.com/onsi/gomega"
--      "github.com/sirupsen/logrus/hooks/test"
--)
--
--var _ = Describe("Downloader", func() {
--      var (
--              sutConfig                     config.DownloaderConfig
--              sut                           *httpDownloader
--              failedDownloadCountEvtChannel chan string
--              loggerHook                    *test.Hook
--      )
--      BeforeEach(func() {
--              var err error
--
--              sutConfig, err = config.WithDefaults[config.DownloaderConfig]()
--              Expect(err).Should(Succeed())
--
--              failedDownloadCountEvtChannel = make(chan string, 5)
--              // collect received events in the channel
--              fn := func(url string) {
--                      failedDownloadCountEvtChannel <- url
--              }
--              Expect(Bus().Subscribe(CachingFailedDownloadChanged, 
fn)).Should(Succeed())
--              DeferCleanup(func() {
--                      Expect(Bus().Unsubscribe(CachingFailedDownloadChanged, 
fn))
--              })
--
--              loggerHook = test.NewGlobal()
--              log.Log().AddHook(loggerHook)
--              DeferCleanup(loggerHook.Reset)
--      })
--
--      JustBeforeEach(func() {
--              sut = newDownloader(sutConfig, nil)
--      })
--
--      Describe("NewDownloader", func() {
--              It("Should use provided parameters", func() {
--                      transport := &http.Transport{}
--
--                      sut = NewDownloader(
--                              config.DownloaderConfig{
--                                      Attempts: 5,
--                                      Cooldown: config.Duration(2 * 
time.Second),
--                                      Timeout:  config.Duration(5 * 
time.Second),
--                              },
--                              transport,
--                      ).(*httpDownloader)
--
--                      Expect(sut.cfg.Attempts).Should(BeNumerically("==", 5))
--                      Expect(sut.cfg.Timeout).Should(BeNumerically("==", 
5*time.Second))
--                      Expect(sut.cfg.Cooldown).Should(BeNumerically("==", 
2*time.Second))
--                      
Expect(sut.client.Transport).Should(BeIdenticalTo(transport))
--              })
--      })
--
--      Describe("Download of a file", func() {
--              var server *httptest.Server
--              When("Download was successful", func() {
--                      BeforeEach(func() {
--                              server = TestServer("line.one\nline.two")
--                              DeferCleanup(server.Close)
--
--                              sut = newDownloader(sutConfig, nil)
--                      })
--                      It("Should return all lines from the file", func() {
--                              reader, err := sut.DownloadFile(server.URL)
--
--                              Expect(err).Should(Succeed())
--                              Expect(reader).Should(Not(BeNil()))
--                              DeferCleanup(reader.Close)
--                              buf := new(strings.Builder)
--                              _, err = io.Copy(buf, reader)
--                              Expect(err).Should(Succeed())
--                              
Expect(buf.String()).Should(Equal("line.one\nline.two"))
--                      })
--              })
--              When("Server returns NOT_FOUND (404)", func() {
--                      BeforeEach(func() {
--                              server = 
httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req 
*http.Request) {
--                                      rw.WriteHeader(http.StatusNotFound)
--                              }))
--                              DeferCleanup(server.Close)
--
--                              sutConfig.Attempts = 3
--                      })
--                      It("Should return error", func() {
--                              reader, err := sut.DownloadFile(server.URL)
--
--                              Expect(err).Should(HaveOccurred())
--                              Expect(reader).Should(BeNil())
--                              Expect(err.Error()).Should(Equal("got status 
code 404"))
--                              
Expect(failedDownloadCountEvtChannel).Should(HaveLen(3))
--                              
Expect(failedDownloadCountEvtChannel).Should(Receive(Equal(server.URL)))
--                      })
--              })
--              When("Wrong URL is defined", func() {
--                      BeforeEach(func() {
--                              sutConfig.Attempts = 1
--                      })
--                      It("Should return error", func() {
--                              _, err := sut.DownloadFile("somewrongurl")
--
--                              Expect(err).Should(HaveOccurred())
--                              
Expect(loggerHook.LastEntry().Message).Should(ContainSubstring("Can't download 
file: "))
--                              // failed download event was emitted only once
--                              
Expect(failedDownloadCountEvtChannel).Should(HaveLen(1))
--                              
Expect(failedDownloadCountEvtChannel).Should(Receive(Equal("somewrongurl")))
--                      })
--              })
--
--              When("If timeout occurs on first request", func() {
--                      var attempt uint64 = 1
--
--                      BeforeEach(func() {
--                              sutConfig = config.DownloaderConfig{
--                                      Timeout:  config.Duration(20 * 
time.Millisecond),
--                                      Attempts: 3,
--                                      Cooldown: 
config.Duration(time.Millisecond),
--                              }
--
--                              // should produce a timeout on first attempt
--                              server = 
httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req 
*http.Request) {
--                                      a := atomic.LoadUint64(&attempt)
--                                      atomic.AddUint64(&attempt, 1)
--                                      if a == 1 {
--                                              time.Sleep(500 * 
time.Millisecond)
--                                      } else {
--                                              _, err := 
rw.Write([]byte("blocked1.com"))
--                                              Expect(err).Should(Succeed())
--                                      }
--                              }))
--                              DeferCleanup(server.Close)
--                      })
--                      It("Should perform a retry and return file content", 
func() {
--                              reader, err := sut.DownloadFile(server.URL)
--                              Expect(err).Should(Succeed())
--                              Expect(reader).Should(Not(BeNil()))
--                              DeferCleanup(reader.Close)
--
--                              buf := new(strings.Builder)
--                              _, err = io.Copy(buf, reader)
--                              Expect(err).Should(Succeed())
--                              
Expect(buf.String()).Should(Equal("blocked1.com"))
--
--                              // failed download event was emitted only once
--                              
Expect(failedDownloadCountEvtChannel).Should(HaveLen(1))
--                              
Expect(failedDownloadCountEvtChannel).Should(Receive(Equal(server.URL)))
--                              
Expect(loggerHook.LastEntry().Message).Should(ContainSubstring("Temporary 
network err / Timeout occurred: "))
--                      })
--              })
--              When("If timeout occurs on all request", func() {
--                      BeforeEach(func() {
--                              sutConfig = config.DownloaderConfig{
--                                      Timeout:  config.Duration(10 * 
time.Millisecond),
--                                      Attempts: 3,
--                                      Cooldown: 
config.Duration(time.Millisecond),
--                              }
--
--                              // should always produce a timeout
--                              server = 
httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, req 
*http.Request) {
--                                      time.Sleep(20 * time.Millisecond)
--                              }))
--                              DeferCleanup(server.Close)
--                      })
--                      It("Should perform a retry until max retry attempt 
count is reached and return TransientError", func() {
--                              reader, err := sut.DownloadFile(server.URL)
--                              Expect(err).Should(HaveOccurred())
--                              Expect(errors.As(err, 
new(*TransientError))).Should(BeTrue())
--                              
Expect(err.Error()).Should(ContainSubstring("Timeout"))
--                              Expect(reader).Should(BeNil())
--
--                              // failed download event was emitted 3 times
--                              
Expect(failedDownloadCountEvtChannel).Should(HaveLen(3))
--                              
Expect(failedDownloadCountEvtChannel).Should(Receive(Equal(server.URL)))
--                      })
--              })
--              When("DNS resolution of passed URL fails", func() {
--                      BeforeEach(func() {
--                              sutConfig = config.DownloaderConfig{
--                                      Timeout:  config.Duration(500 * 
time.Millisecond),
--                                      Attempts: 3,
--                                      Cooldown: 200 * 
config.Duration(time.Millisecond),
--                              }
--                      })
--                      It("Should perform a retry until max retry attempt 
count is reached and return DNSError", func() {
--                              reader, err := 
sut.DownloadFile("http://some.domain.which.does.not.exist";)
--                              Expect(err).Should(HaveOccurred())
--
--                              var dnsError *net.DNSError
--                              Expect(errors.As(err, 
&dnsError)).Should(BeTrue(), "received error %w", err)
--                              Expect(reader).Should(BeNil())
--
--                              // failed download event was emitted 3 times
--                              
Expect(failedDownloadCountEvtChannel).Should(HaveLen(3))
--                              
Expect(failedDownloadCountEvtChannel).Should(Receive(Equal("http://some.domain.which.does.not.exist";)))
--                              
Expect(loggerHook.LastEntry().Message).Should(ContainSubstring("Name resolution 
err: "))
--                      })
--              })
--      })
--})
-diff --git a/lists/list_cache_benchmark_test.go 
b/lists/list_cache_benchmark_test.go
-deleted file mode 100644
-index fedf2fd..0000000
---- a/lists/list_cache_benchmark_test.go
-+++ /dev/null
-@@ -1,29 +0,0 @@
--package lists
--
--import (
--      "testing"
--
--      "github.com/0xERR0R/blocky/config"
--)
--
--func BenchmarkRefresh(b *testing.B) {
--      file1, _ := createTestListFile(b.TempDir(), 100000)
--      file2, _ := createTestListFile(b.TempDir(), 150000)
--      file3, _ := createTestListFile(b.TempDir(), 130000)
--      lists := map[string][]config.BytesSource{
--              "gr1": config.NewBytesSources(file1, file2, file3),
--      }
--
--      cfg := config.SourceLoadingConfig{
--              Concurrency:   5,
--              RefreshPeriod: config.Duration(-1),
--      }
--      downloader := NewDownloader(config.DownloaderConfig{}, nil)
--      cache, _ := NewListCache(ListCacheTypeBlacklist, cfg, lists, downloader)
--
--      b.ReportAllocs()
--
--      for n := 0; n < b.N; n++ {
--              cache.Refresh()
--      }
--}
-diff --git a/lists/list_cache_test.go b/lists/list_cache_test.go
-deleted file mode 100644
-index 2d08cfb..0000000
---- a/lists/list_cache_test.go
-+++ /dev/null
-@@ -1,496 +0,0 @@
--package lists
--
--import (
--      "bufio"
--      "context"
--      "errors"
--      "fmt"
--      "io"
--      "math/rand"
--      "net/http/httptest"
--      "os"
--      "strings"
--
--      "github.com/0xERR0R/blocky/config"
--      . "github.com/0xERR0R/blocky/evt"
--      "github.com/0xERR0R/blocky/lists/parsers"
--      "github.com/0xERR0R/blocky/log"
--      "github.com/0xERR0R/blocky/util"
--      "github.com/sirupsen/logrus"
--
--      . "github.com/0xERR0R/blocky/helpertest"
--      . "github.com/onsi/ginkgo/v2"
--      . "github.com/onsi/gomega"
--)
--
--var _ = Describe("ListCache", func() {
--      var (
--              tmpDir                         *TmpFolder
--              emptyFile, file1, file2, file3 *TmpFile
--              server1, server2, server3      *httptest.Server
--
--              sut       *ListCache
--              sutConfig config.SourceLoadingConfig
--
--              listCacheType  ListCacheType
--              lists          map[string][]config.BytesSource
--              downloader     FileDownloader
--              mockDownloader *MockDownloader
--      )
--
--      BeforeEach(func() {
--              var err error
--
--              listCacheType = ListCacheTypeBlacklist
--
--              sutConfig, err = 
config.WithDefaults[config.SourceLoadingConfig]()
--              Expect(err).Should(Succeed())
--
--              sutConfig.RefreshPeriod = -1
--
--              downloader = NewDownloader(config.DownloaderConfig{}, nil)
--              mockDownloader = nil
--
--              server1 = 
TestServer("blocked1.com\nblocked1a.com\n192.168.178.55")
--              DeferCleanup(server1.Close)
--              server2 = TestServer("blocked2.com")
--              DeferCleanup(server2.Close)
--              server3 = TestServer("blocked3.com\nblocked1a.com")
--              DeferCleanup(server3.Close)
--
--              tmpDir = NewTmpFolder("ListCache")
--              Expect(tmpDir.Error).Should(Succeed())
--              DeferCleanup(tmpDir.Clean)
--
--              emptyFile = tmpDir.CreateStringFile("empty", "#empty file")
--              Expect(emptyFile.Error).Should(Succeed())
--
--              emptyFile = tmpDir.CreateStringFile("empty", "#empty file")
--              Expect(emptyFile.Error).Should(Succeed())
--              file1 = tmpDir.CreateStringFile("file1", "blocked1.com", 
"blocked1a.com")
--              Expect(file1.Error).Should(Succeed())
--              file2 = tmpDir.CreateStringFile("file2", "blocked2.com")
--              Expect(file2.Error).Should(Succeed())
--              file3 = tmpDir.CreateStringFile("file3", "blocked3.com", 
"blocked1a.com")
--              Expect(file3.Error).Should(Succeed())
--      })
--
--      JustBeforeEach(func() {
--              var err error
--
--              Expect(lists).ShouldNot(BeNil(), "bad test: forgot to set 
`lists`")
--
--              if mockDownloader != nil {
--                      downloader = mockDownloader
--              }
--
--              sut, err = NewListCache(listCacheType, sutConfig, lists, 
downloader)
--              Expect(err).Should(Succeed())
--      })
--
--      Describe("List cache and matching", func() {
--              When("List is empty", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr0": 
config.NewBytesSources(emptyFile.Path),
--                              }
--                      })
--
--                      When("Query with empty", func() {
--                              It("should not panic", func() {
--                                      group := sut.Match("", []string{"gr0"})
--                                      Expect(group).Should(BeEmpty())
--                              })
--                      })
--
--                      It("should not match anything", func() {
--                              group := sut.Match("google.com", 
[]string{"gr1"})
--                              Expect(group).Should(BeEmpty())
--                      })
--              })
--              When("List becomes empty on refresh", func() {
--                      BeforeEach(func() {
--                              mockDownloader = newMockDownloader(func(res 
chan<- string, err chan<- error) {
--                                      res <- "blocked1.com"
--                                      res <- "# nothing"
--                              })
--
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": {mockDownloader.ListSource()},
--                              }
--                      })
--
--                      It("should delete existing elements from group cache", 
func(ctx context.Context) {
--                              group := sut.Match("blocked1.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              err := sut.refresh(ctx)
--                              Expect(err).Should(Succeed())
--
--                              group = sut.Match("blocked1.com", 
[]string{"gr1"})
--                              Expect(group).Should(BeEmpty())
--                      })
--              })
--              When("List has invalid lines", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": {
--                                              config.TextBytesSource(
--                                                      "inlinedomain1.com",
--                                                      "invaliddomain!",
--                                                      "inlinedomain2.com",
--                                              ),
--                                      },
--                              }
--                      })
--
--                      It("should still other domains", func() {
--                              group := sut.Match("inlinedomain1.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("inlinedomain2.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--                      })
--              })
--              When("a temporary/transient err occurs on download", func() {
--                      BeforeEach(func() {
--                              // should produce a transient error on second 
and third attempt
--                              mockDownloader = newMockDownloader(func(res 
chan<- string, err chan<- error) {
--                                      res <- "blocked1.com\nblocked2.com\n"
--                                      err <- &TransientError{inner: 
errors.New("boom")}
--                                      err <- &TransientError{inner: 
errors.New("boom")}
--                              })
--
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": {mockDownloader.ListSource()},
--                              }
--                      })
--
--                      It("should not delete existing elements from group 
cache", func(ctx context.Context) {
--                              By("Lists loaded without timeout", func() {
--                                      Eventually(func(g Gomega) {
--                                              group := 
sut.Match("blocked1.com", []string{"gr1"})
--                                              
g.Expect(group).Should(ContainElement("gr1"))
--                                      }, "1s").Should(Succeed())
--                              })
--
--                              Expect(sut.refresh(ctx)).Should(HaveOccurred())
--
--                              By("List couldn't be loaded due to timeout", 
func() {
--                                      group := sut.Match("blocked1.com", 
[]string{"gr1"})
--                                      
Expect(group).Should(ContainElement("gr1"))
--                              })
--
--                              sut.Refresh()
--
--                              By("List couldn't be loaded due to timeout", 
func() {
--                                      group := sut.Match("blocked1.com", 
[]string{"gr1"})
--                                      
Expect(group).Should(ContainElement("gr1"))
--                              })
--                      })
--              })
--              When("non transient err occurs on download", func() {
--                      BeforeEach(func() {
--                              // should produce a non transient error on 
second attempt
--                              mockDownloader = newMockDownloader(func(res 
chan<- string, err chan<- error) {
--                                      res <- "blocked1.com"
--                                      err <- errors.New("boom")
--                              })
--
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": {mockDownloader.ListSource()},
--                              }
--                      })
--
--                      It("should keep existing elements from group cache", 
func(ctx context.Context) {
--                              By("Lists loaded without err", func() {
--                                      group := sut.Match("blocked1.com", 
[]string{"gr1"})
--                                      
Expect(group).Should(ContainElement("gr1"))
--                              })
--
--                              Expect(sut.refresh(ctx)).Should(HaveOccurred())
--
--                              By("Lists from first load is kept", func() {
--                                      group := sut.Match("blocked1.com", 
[]string{"gr1"})
--                                      
Expect(group).Should(ContainElement("gr1"))
--                              })
--                      })
--              })
--              When("Configuration has 3 external working urls", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": 
config.NewBytesSources(server1.URL, server2.URL),
--                                      "gr2": 
config.NewBytesSources(server3.URL),
--                              }
--                      })
--
--                      It("should download the list and match against", func() 
{
--                              group := sut.Match("blocked1.com", 
[]string{"gr1", "gr2"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("blocked1a.com", 
[]string{"gr1", "gr2"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("blocked1a.com", 
[]string{"gr2"})
--                              Expect(group).Should(ContainElement("gr2"))
--                      })
--              })
--              When("Configuration has some faulty urls", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": 
config.NewBytesSources(server1.URL, server2.URL, "doesnotexist"),
--                                      "gr2": 
config.NewBytesSources(server3.URL, "someotherfile"),
--                              }
--                      })
--
--                      It("should download the list and match against", func() 
{
--                              group := sut.Match("blocked1.com", 
[]string{"gr1", "gr2"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("blocked1a.com", 
[]string{"gr1", "gr2"})
--                              Expect(group).Should(ContainElements("gr1", 
"gr2"))
--
--                              group = sut.Match("blocked1a.com", 
[]string{"gr2"})
--                              Expect(group).Should(ContainElement("gr2"))
--                      })
--              })
--              When("List will be updated", func() {
--                      resultCnt := 0
--
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": 
config.NewBytesSources(server1.URL),
--                              }
--
--                              _ = 
Bus().SubscribeOnce(BlockingCacheGroupChanged, func(listType ListCacheType, 
group string, cnt int) {
--                                      resultCnt = cnt
--                              })
--                      })
--
--                      It("event should be fired and contain count of elements 
in downloaded lists", func() {
--                              group := sut.Match("blocked1.com", []string{})
--                              Expect(group).Should(BeEmpty())
--                              Expect(resultCnt).Should(Equal(3))
--                      })
--              })
--              When("multiple groups are passed", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": 
config.NewBytesSources(file1.Path, file2.Path),
--                                      "gr2": config.NewBytesSources("file://" 
+ file3.Path),
--                              }
--                      })
--
--                      It("should match", func() {
--                              
Expect(sut.groupedCache.ElementCount("gr1")).Should(Equal(3))
--                              
Expect(sut.groupedCache.ElementCount("gr2")).Should(Equal(2))
--
--                              group := sut.Match("blocked1.com", 
[]string{"gr1", "gr2"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("blocked1a.com", 
[]string{"gr1", "gr2"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("blocked1a.com", 
[]string{"gr2"})
--                              Expect(group).Should(ContainElement("gr2"))
--                      })
--              })
--              When("group with bigger files", func() {
--                      It("should match", func() {
--                              file1, lines1 := 
createTestListFile(GinkgoT().TempDir(), 10000)
--                              file2, lines2 := 
createTestListFile(GinkgoT().TempDir(), 15000)
--                              file3, lines3 := 
createTestListFile(GinkgoT().TempDir(), 13000)
--                              lists := map[string][]config.BytesSource{
--                                      "gr1": config.NewBytesSources(file1, 
file2, file3),
--                              }
--
--                              sut, err := 
NewListCache(ListCacheTypeBlacklist, sutConfig, lists, downloader)
--                              Expect(err).Should(Succeed())
--
--                              
Expect(sut.groupedCache.ElementCount("gr1")).Should(Equal(lines1 + lines2 + 
lines3))
--                      })
--              })
--              When("inline list content is defined", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": {config.TextBytesSource(
--                                              "inlinedomain1.com",
--                                              "#some comment",
--                                              "inlinedomain2.com",
--                                      )},
--                              }
--                      })
--
--                      It("should match", func() {
--                              
Expect(sut.groupedCache.ElementCount("gr1")).Should(Equal(2))
--                              group := sut.Match("inlinedomain1.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("inlinedomain2.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--                      })
--              })
--              When("Text file can't be parsed", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": {
--                                              config.TextBytesSource(
--                                                      "inlinedomain1.com",
--                                                      
"lineTooLong"+strings.Repeat("x", bufio.MaxScanTokenSize), // too long
--                                              ),
--                                      },
--                              }
--                      })
--
--                      It("should still match already imported strings", 
func() {
--                              group := sut.Match("inlinedomain1.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--                      })
--              })
--              When("Text file has too many errors", func() {
--                      BeforeEach(func() {
--                              sutConfig.MaxErrorsPerSource = 0
--                              sutConfig.Strategy = 
config.StartStrategyTypeFailOnError
--                      })
--                      It("should fail parsing", func() {
--                              lists := map[string][]config.BytesSource{
--                                      "gr1": {
--                                              
config.TextBytesSource("invaliddomain!"), // too many errors since 
`maxErrorsPerSource` is 0
--                                      },
--                              }
--
--                              _, err := NewListCache(ListCacheTypeBlacklist, 
sutConfig, lists, downloader)
--                              Expect(err).ShouldNot(Succeed())
--                              
Expect(err).Should(MatchError(parsers.ErrTooManyErrors))
--                      })
--              })
--              When("file has end of line comment", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": 
{config.TextBytesSource("inlinedomain1.com#a comment")},
--                              }
--                      })
--
--                      It("should still parse the domain", func() {
--                              group := sut.Match("inlinedomain1.com", 
[]string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--                      })
--              })
--              When("inline regex content is defined", func() {
--                      BeforeEach(func() {
--                              lists = map[string][]config.BytesSource{
--                                      "gr1": 
{config.TextBytesSource("/^apple\\.(de|com)$/")},
--                              }
--                      })
--
--                      It("should match", func() {
--                              group := sut.Match("apple.com", []string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--
--                              group = sut.Match("apple.de", []string{"gr1"})
--                              Expect(group).Should(ContainElement("gr1"))
--                      })
--              })
--      })
--      Describe("LogConfig", func() {
--              var (
--                      logger *logrus.Entry
--                      hook   *log.MockLoggerHook
--              )
--
--              BeforeEach(func() {
--                      logger, hook = log.NewMockEntry()
--              })
--
--              It("should print list configuration", func() {
--                      lists := map[string][]config.BytesSource{
--                              "gr1": config.NewBytesSources(server1.URL, 
server2.URL),
--                              "gr2": {config.TextBytesSource("inline", 
"definition")},
--                      }
--
--                      sut, err := NewListCache(ListCacheTypeBlacklist, 
sutConfig, lists, downloader)
--                      Expect(err).Should(Succeed())
--
--                      sut.LogConfig(logger)
--                      Expect(hook.Calls).ShouldNot(BeEmpty())
--                      
Expect(hook.Messages).Should(ContainElement(ContainSubstring("gr1:")))
--                      
Expect(hook.Messages).Should(ContainElement(ContainSubstring("gr2:")))
--                      
Expect(hook.Messages).Should(ContainElement(ContainSubstring("TOTAL:")))
--              })
--      })
--
--      Describe("StartStrategy", func() {
--              When("async load is enabled", func() {
--                      BeforeEach(func() {
--                              sutConfig.Strategy = 
config.StartStrategyTypeFast
--                      })
--
--                      It("should never return an error", func() {
--                              lists := map[string][]config.BytesSource{
--                                      "gr1": 
config.NewBytesSources("doesnotexist"),
--                              }
--
--                              _, err := NewListCache(ListCacheTypeBlacklist, 
sutConfig, lists, downloader)
--                              Expect(err).Should(Succeed())
--                      })
--              })
--      })
--})
--
--type MockDownloader struct {
--      util.MockCallSequence[string]
--}
--
--func newMockDownloader(driver func(res chan<- string, err chan<- error)) 
*MockDownloader {
--      return &MockDownloader{util.NewMockCallSequence(driver)}
--}
--
--func (m *MockDownloader) DownloadFile(_ string) (io.ReadCloser, error) {
--      str, err := m.Call()
--      if err != nil {
--              return nil, err
--      }
--
--      return io.NopCloser(strings.NewReader(str)), nil
--}
--
--func (m *MockDownloader) ListSource() config.BytesSource {
--      return config.BytesSource{
--              Type: config.BytesSourceTypeHttp,
--              From: "http://mock-downloader";,
--      }
--}
--
--func createTestListFile(dir string, totalLines int) (string, int) {
--      file, err := os.CreateTemp(dir, "blocky")
--      if err != nil {
--              log.Log().Fatal(err)
--      }
--
--      w := bufio.NewWriter(file)
--      for i := 0; i < totalLines; i++ {
--              fmt.Fprintln(w, RandStringBytes(8+rand.Intn(10))+".com")
--      }
--      w.Flush()
--
--      return file.Name(), totalLines
--}
--
--const (
--      initCharpool = "abcdefghijklmnopqrstuvwxyz"
--      contCharpool = initCharpool + "0123456789-"
--)
--
--func RandStringBytes(n int) string {
--      b := make([]byte, n)
--
--      pool := initCharpool
--
--      for i := range b {
--              b[i] = pool[rand.Intn(len(pool))]
--
--              pool = contCharpool
--      }
--
--      return string(b)
--}
-diff --git a/server/server_test.go b/server/server_test.go
-deleted file mode 100644
-index 65b30bc..0000000
---- a/server/server_test.go
-+++ /dev/null
-@@ -1,888 +0,0 @@
--package server
--
--import (
--      "bytes"
--      "encoding/base64"
--      "encoding/json"
--      "io"
--      "net"
--      "net/http"
--      "strings"
--      "sync/atomic"
--      "time"
--
--      "github.com/0xERR0R/blocky/api"
--      "github.com/0xERR0R/blocky/config"
--      . "github.com/0xERR0R/blocky/helpertest"
--      . "github.com/0xERR0R/blocky/log"
--      "github.com/0xERR0R/blocky/model"
--      "github.com/0xERR0R/blocky/resolver"
--      "github.com/0xERR0R/blocky/util"
--      "github.com/creasty/defaults"
--      . "github.com/onsi/ginkgo/v2"
--      . "github.com/onsi/gomega"
--
--      "github.com/miekg/dns"
--)
--
--var (
--      mockClientName atomic.Value
--      sut            *Server
--      err            error
--)
--
--var _ = BeforeSuite(func() {
--      var upstreamGoogle, upstreamFritzbox, upstreamClient config.Upstream
--      googleMockUpstream := 
resolver.NewMockUDPUpstreamServer().WithAnswerFn(func(request *dns.Msg) 
(response *dns.Msg) {
--              if request.Question[0].Name == "error." {
--                      return nil
--              }
--              response, err := util.NewMsgWithAnswer(
--                      util.ExtractDomain(request.Question[0]), 123, A, 
"123.124.122.122",
--              )
--
--              Expect(err).Should(Succeed())
--
--              return response
--      })
--      DeferCleanup(googleMockUpstream.Close)
--
--      fritzboxMockUpstream := 
resolver.NewMockUDPUpstreamServer().WithAnswerFn(func(request *dns.Msg) 
(response *dns.Msg) {
--              response, err := util.NewMsgWithAnswer(
--                      util.ExtractDomain(request.Question[0]), 3600, A, 
"192.168.178.2",
--              )
--
--              Expect(err).Should(Succeed())
--
--              return response
--      })
--      DeferCleanup(fritzboxMockUpstream.Close)
--
--      clientMockUpstream := 
resolver.NewMockUDPUpstreamServer().WithAnswerFn(func(request *dns.Msg) 
(response *dns.Msg) {
--              var clientName string
--              client := mockClientName.Load()
--
--              if client != nil {
--                      clientName = mockClientName.Load().(string)
--              }
--
--              response, err := util.NewMsgWithAnswer(
--                      util.ExtractDomain(request.Question[0]), 3600, 
dns.Type(dns.TypePTR), clientName,
--              )
--
--              Expect(err).Should(Succeed())
--
--              return response
--      })
--      DeferCleanup(clientMockUpstream.Close)
--
--      upstreamClient = clientMockUpstream.Start()
--      upstreamFritzbox = fritzboxMockUpstream.Start()
--      upstreamGoogle = googleMockUpstream.Start()
--
--      tmpDir := NewTmpFolder("server")
--      Expect(tmpDir.Error).Should(Succeed())
--      DeferCleanup(tmpDir.Clean)
--
--      certPem := writeCertPem(tmpDir)
--      Expect(certPem.Error).Should(Succeed())
--
--      keyPem := writeKeyPem(tmpDir)
--      Expect(keyPem.Error).Should(Succeed())
--
--      doubleclickFile := tmpDir.CreateStringFile("doubleclick.net.txt", 
"doubleclick.net", "doubleclick.net.cn")
--      Expect(doubleclickFile.Error).Should(Succeed())
--
--      bildFile := tmpDir.CreateStringFile("www.bild.de.txt", "www.bild.de")
--      Expect(bildFile.Error).Should(Succeed())
--
--      heiseFile := tmpDir.CreateStringFile("heise.de.txt", "heise.de")
--      Expect(heiseFile.Error).Should(Succeed())
--
--      youtubeFile := tmpDir.CreateStringFile("youtube.com.txt", "youtube.com")
--      Expect(youtubeFile.Error).Should(Succeed())
--
--      // create server
--      sut, err = NewServer(&config.Config{
--              CustomDNS: config.CustomDNSConfig{
--                      CustomTTL: config.Duration(3600 * time.Second),
--                      Mapping: config.CustomDNSMapping{
--                              HostIPs: map[string][]net.IP{
--                                      "custom.lan": 
{net.ParseIP("192.168.178.55")},
--                                      "lan.home":   
{net.ParseIP("192.168.178.56")},
--                              },
--                      },
--              },
--              Conditional: config.ConditionalUpstreamConfig{
--                      Mapping: config.ConditionalUpstreamMapping{
--                              Upstreams: map[string][]config.Upstream{
--                                      "net.cn":    {upstreamClient},
--                                      "fritz.box": {upstreamFritzbox},
--                              },
--                      },
--              },
--              Blocking: config.BlockingConfig{
--                      BlackLists: map[string][]config.BytesSource{
--                              "ads": config.NewBytesSources(
--                                      doubleclickFile.Path,
--                                      bildFile.Path,
--                                      heiseFile.Path,
--                              ),
--                              "youtube": 
config.NewBytesSources(youtubeFile.Path),
--                      },
--                      WhiteLists: map[string][]config.BytesSource{
--                              "ads":       
config.NewBytesSources(heiseFile.Path),
--                              "whitelist": 
config.NewBytesSources(heiseFile.Path),
--                      },
--                      ClientGroupsBlock: map[string][]string{
--                              "default":         {"ads"},
--                              "clWhitelistOnly": {"whitelist"},
--                              "clAdsAndYoutube": {"ads", "youtube"},
--                              "clYoutubeOnly":   {"youtube"},
--                      },
--                      BlockType: "zeroIp",
--                      BlockTTL:  config.Duration(6 * time.Hour),
--              },
--              Upstreams: config.UpstreamsConfig{
--                      Groups: map[string][]config.Upstream{"default": 
{upstreamGoogle}},
--              },
--              ClientLookup: config.ClientLookupConfig{
--                      Upstream: upstreamClient,
--              },
--
--              Ports: config.PortsConfig{
--                      DNS:   config.ListenConfig{"55555"},
--                      TLS:   config.ListenConfig{"8853"},
--                      HTTP:  config.ListenConfig{"4000"},
--                      HTTPS: config.ListenConfig{"4443"},
--              },
--              CertFile: certPem.Path,
--              KeyFile:  keyPem.Path,
--              Prometheus: config.MetricsConfig{
--                      Enable: true,
--                      Path:   "/metrics",
--              },
--      })
--
--      Expect(err).Should(Succeed())
--
--      errChan := make(chan error, 10)
--
--      // start server
--      go func() {
--              sut.Start(errChan)
--      }()
--      DeferCleanup(sut.Stop)
--
--      Consistently(errChan, "1s").ShouldNot(Receive())
--})
--
--var _ = Describe("Running DNS server", func() {
--      Describe("performing DNS request with running server", func() {
--              BeforeEach(func() {
--                      mockClientName.Store("")
--                      // reset client cache
--                      res := sut.queryResolver
--                      for res != nil {
--                              if t, ok := 
res.(*resolver.ClientNamesResolver); ok {
--                                      t.FlushCache()
--
--                                      break
--                              }
--                              if c, ok := res.(resolver.ChainedResolver); ok {
--                                      res = c.GetNext()
--                              } else {
--                                      break
--                              }
--                      }
--              })
--
--              Context("DNS query is resolvable via external DNS", func() {
--                      It("should return valid answer", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("google.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("google.de.", A, "123.124.122.122"),
--                                                      
HaveTTL(BeNumerically("==", 123)),
--                                              ))
--                      })
--              })
--              Context("Custom DNS entry with exact match", func() {
--                      It("should return valid answer", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("custom.lan.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("custom.lan.", A, "192.168.178.55"),
--                                                      
HaveTTL(BeNumerically("==", 3600)),
--                                              ))
--                      })
--              })
--              Context("Custom DNS entry with sub domain", func() {
--                      It("should return valid answer", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("host.lan.home.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("host.lan.home.", A, "192.168.178.56"),
--                                                      
HaveTTL(BeNumerically("==", 3600)),
--                                              ))
--                      })
--              })
--              Context("Conditional upstream", func() {
--                      It("should resolve query via conditional upstream 
resolver", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("host.fritz.box.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("host.fritz.box.", A, "192.168.178.2"),
--                                                      
HaveTTL(BeNumerically("==", 3600)),
--                                              ))
--                      })
--              })
--              Context("Conditional upstream blocking", func() {
--                      It("Query should be blocked, domain is in default 
group", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("doubleclick.net.cn.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("doubleclick.net.cn.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--                      })
--              })
--              Context("Blocking default group", func() {
--                      It("Query should be blocked, domain is in default 
group", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("doubleclick.net.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("doubleclick.net.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--                      })
--              })
--              Context("Blocking default group with sub domain", func() {
--                      It("Query with subdomain should be blocked, domain is 
in default group", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("www.bild.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("www.bild.de.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--                      })
--              })
--              Context("no blocking default group with sub domain", func() {
--                      It("Query with should not be blocked, sub domain is not 
in blacklist", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("bild.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      BeDNSRecord("bild.de.", 
A, "123.124.122.122"),
--                                                      
HaveTTL(BeNumerically("<=", 123)),
--                                              ))
--                      })
--              })
--              Context("domain is on white and blacklist default group", 
func() {
--                      It("Query with should not be blocked, domain is on 
white and blacklist", func() {
--                              
Expect(requestServer(util.NewMsgWithQuestion("heise.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("heise.de.", A, "123.124.122.122"),
--                                                      
HaveTTL(BeNumerically("<=", 123)),
--                                              ))
--                      })
--              })
--              Context("domain is on client specific white list", func() {
--                      It("Query with should not be blocked, domain is on 
client's white list", func() {
--                              mockClientName.Store("clWhitelistOnly")
--                              
Expect(requestServer(util.NewMsgWithQuestion("heise.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("heise.de.", A, "123.124.122.122"),
--                                                      
HaveTTL(BeNumerically("<=", 123)),
--                                              ))
--                      })
--              })
--              Context("block client whitelist only", func() {
--                      It("Query with should be blocked, client has only 
whitelist, domain is not on client's white list", func() {
--                              mockClientName.Store("clWhitelistOnly")
--                              
Expect(requestServer(util.NewMsgWithQuestion("google.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("google.de.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--                      })
--              })
--              Context("block client with 2 groups", func() {
--                      It("Query with should be blocked, domain is on black 
list", func() {
--                              mockClientName.Store("clAdsAndYoutube")
--
--                              
Expect(requestServer(util.NewMsgWithQuestion("www.bild.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("www.bild.de.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--
--                              
Expect(requestServer(util.NewMsgWithQuestion("youtube.com.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("youtube.com.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--                      })
--              })
--              Context("client with 1 group: no block if domain in other 
group", func() {
--                      It("Query with should not be blocked, domain is on 
black list in another group", func() {
--                              mockClientName.Store("clYoutubeOnly")
--
--                              
Expect(requestServer(util.NewMsgWithQuestion("www.bild.de.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("www.bild.de.", A, "123.124.122.122"),
--                                                      
HaveTTL(BeNumerically("<=", 123)),
--                                              ))
--                      })
--              })
--              Context("block client with 1 group", func() {
--                      It("Query with should not  blocked, domain is on black 
list in client's group", func() {
--                              mockClientName.Store("clYoutubeOnly")
--
--                              
Expect(requestServer(util.NewMsgWithQuestion("youtube.com.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
BeDNSRecord("youtube.com.", A, "0.0.0.0"),
--                                                      
HaveTTL(BeNumerically("==", 21600)),
--                                              ))
--                      })
--              })
--              Context("health check", func() {
--                      It("Should always return dummy response", func() {
--                              resp := 
requestServer(util.NewMsgWithQuestion("healthcheck.blocky.", A))
--
--                              Expect(resp.Answer).Should(BeEmpty())
--                      })
--              })
--      })
--
--      Describe("Prometheus endpoint", func() {
--              When("Prometheus URL is called", func() {
--                      It("should return prometheus data", func() {
--                              resp, err := 
http.Get("http://localhost:4000/metrics";)
--                              Expect(err).Should(Succeed())
--                              
Expect(resp).Should(HaveHTTPStatus(http.StatusOK))
--                      })
--              })
--      })
--      Describe("Root endpoint", func() {
--              When("Root URL is called", func() {
--                      It("should return root page", func() {
--                              resp, err := http.Get("http://localhost:4000/";)
--                              Expect(err).Should(Succeed())
--                              Expect(resp).Should(
--                                      SatisfyAll(
--                                              HaveHTTPStatus(http.StatusOK),
--                                              
HaveHTTPHeaderWithValue("Content-type", "text/html; charset=UTF-8"),
--                                      ))
--                      })
--              })
--      })
--
--      Describe("Query Rest API", func() {
--              When("Query API is called", func() {
--                      It("Should process the query", func() {
--                              req := api.QueryRequest{
--                                      Query: "google.de",
--                                      Type:  "A",
--                              }
--                              jsonValue, err := json.Marshal(req)
--                              Expect(err).Should(Succeed())
--
--                              resp, err := 
http.Post("http://localhost:4000/api/query";, "application/json", 
bytes.NewBuffer(jsonValue))
--
--                              Expect(err).Should(Succeed())
--                              defer resp.Body.Close()
--
--                              Expect(resp).Should(
--                                      SatisfyAll(
--                                              HaveHTTPStatus(http.StatusOK),
--                                              
HaveHTTPHeaderWithValue("Content-type", "application/json"),
--                                      ))
--
--                              var result api.QueryResult
--                              err = json.NewDecoder(resp.Body).Decode(&result)
--                              Expect(err).Should(Succeed())
--                              Expect(result.Response).Should(Equal("A 
(123.124.122.122)"))
--                      })
--              })
--              When("Wrong request type is used", func() {
--                      It("Should return internal error", func() {
--                              req := api.QueryRequest{
--                                      Query: "google.de",
--                                      Type:  "WrongType",
--                              }
--                              jsonValue, err := json.Marshal(req)
--                              Expect(err).Should(Succeed())
--
--                              resp, err := 
http.Post("http://localhost:4000/api/query";, "application/json", 
bytes.NewBuffer(jsonValue))
--
--                              Expect(err).Should(Succeed())
--                              DeferCleanup(resp.Body.Close)
--
--                              
Expect(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
--                      })
--              })
--              When("Internal error occurs", func() {
--                      It("Should return internal error", func() {
--                              req := api.QueryRequest{
--                                      Query: "error.",
--                                      Type:  "A",
--                              }
--                              jsonValue, err := json.Marshal(req)
--                              Expect(err).Should(Succeed())
--
--                              resp, err := 
http.Post("http://localhost:4000/api/query";, "application/json", 
bytes.NewBuffer(jsonValue))
--                              Expect(err).Should(Succeed())
--                              DeferCleanup(resp.Body.Close)
--                              
Expect(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
--                      })
--              })
--              When("Request is malformed", func() {
--                      It("Should return internal error", func() {
--                              jsonValue := []byte("")
--
--                              resp, err := 
http.Post("http://localhost:4000/api/query";, "application/json", 
bytes.NewBuffer(jsonValue))
--
--                              Expect(err).Should(Succeed())
--                              DeferCleanup(resp.Body.Close)
--
--                              
Expect(resp.StatusCode).Should(Equal(http.StatusInternalServerError))
--                      })
--              })
--      })
--
--      Describe("DOH endpoint", func() {
--              Context("DOH over GET (RFC 8484)", func() {
--                      When("DOH get request with 'example.com' is performed", 
func() {
--                              It("should get a valid response", func() {
--                                      resp, err := 
http.Get("http://localhost:4000/dns-query?dns=AAABAAABAAAAAAAAA3d3dwdleGFtcGxlA2NvbQAAAQAB";)
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusOK))
--                                      
Expect(resp).Should(HaveHTTPHeaderWithValue("Content-type", 
"application/dns-message"))
--
--                                      rawMsg, err := io.ReadAll(resp.Body)
--                                      Expect(err).Should(Succeed())
--
--                                      msg := new(dns.Msg)
--                                      err = msg.Unpack(rawMsg)
--                                      Expect(err).Should(Succeed())
--
--                                      
Expect(msg.Answer).Should(BeDNSRecord("www.example.com.", A, "123.124.122.122"))
--                              })
--                      })
--                      When("Request does not contain a valid DNS message", 
func() {
--                              It("should return 'Bad Request'", func() {
--                                      resp, err := 
http.Get("http://localhost:4000/dns-query?dns=xxxx";)
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusBadRequest))
--                              })
--                      })
--                      When("Request's parameter does not contain a valid 
base64'", func() {
--                              It("should return 'Bad Request'", func() {
--                                      resp, err := 
http.Get("http://localhost:4000/dns-query?dns=äöä";)
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusBadRequest))
--                              })
--                      })
--                      When("Request does not contain a dns parameter", func() 
{
--                              It("should return 'Bad Request'", func() {
--                                      resp, err := 
http.Get("http://localhost:4000/dns-query?test";)
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusBadRequest))
--                              })
--                      })
--                      When("Request's dns parameter is too long'", func() {
--                              It("should return 'URI Too Long'", func() {
--                                      longBase64msg := 
base64.StdEncoding.EncodeToString([]byte(strings.Repeat("t", 513)))
--
--                                      resp, err := 
http.Get("http://localhost:4000/dns-query?dns="; + longBase64msg)
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusRequestURITooLong))
--                              })
--                      })
--              })
--              Context("DOH over POST (RFC 8484)", func() {
--                      When("DOH post request with 'example.com' is 
performed", func() {
--                              It("should get a valid response", func() {
--                                      msg := 
util.NewMsgWithQuestion("www.example.com.", A)
--                                      rawDNSMessage, err := msg.Pack()
--                                      Expect(err).Should(Succeed())
--
--                                      resp, err := 
http.Post("http://localhost:4000/dns-query";,
--                                              "application/dns-message", 
bytes.NewReader(rawDNSMessage))
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      Expect(resp).Should(
--                                              SatisfyAll(
--                                                      
HaveHTTPStatus(http.StatusOK),
--                                                      
HaveHTTPHeaderWithValue("Content-type", "application/dns-message"),
--                                              ))
--
--                                      rawMsg, err := io.ReadAll(resp.Body)
--                                      Expect(err).Should(Succeed())
--
--                                      msg = new(dns.Msg)
--                                      err = msg.Unpack(rawMsg)
--                                      Expect(err).Should(Succeed())
--
--                                      
Expect(msg.Answer).Should(BeDNSRecord("www.example.com.", A, "123.124.122.122"))
--                              })
--                              It("should get a valid response, clientId is 
passed", func() {
--                                      msg := 
util.NewMsgWithQuestion("www.example.com.", A)
--                                      rawDNSMessage, err := msg.Pack()
--                                      Expect(err).Should(Succeed())
--
--                                      resp, err := 
http.Post("http://localhost:4000/dns-query/client123";,
--                                              "application/dns-message", 
bytes.NewReader(rawDNSMessage))
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      Expect(resp).Should(
--                                              SatisfyAll(
--                                                      
HaveHTTPStatus(http.StatusOK),
--                                                      
HaveHTTPHeaderWithValue("Content-type", "application/dns-message"),
--                                              ))
--                                      rawMsg, err := io.ReadAll(resp.Body)
--                                      Expect(err).Should(Succeed())
--
--                                      msg = new(dns.Msg)
--                                      err = msg.Unpack(rawMsg)
--                                      Expect(err).Should(Succeed())
--
--                                      
Expect(msg.Answer).Should(BeDNSRecord("www.example.com.", A, "123.124.122.122"))
--                              })
--                      })
--                      When("POST payload exceeds 512 bytes", func() {
--                              It("should return 'Payload Too Large'", func() {
--                                      largeMessage := 
[]byte(strings.Repeat("t", 513))
--
--                                      resp, err := 
http.Post("http://localhost:4000/dns-query";, "application/dns-message", 
bytes.NewReader(largeMessage))
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusRequestEntityTooLarge))
--                              })
--                      })
--                      When("Request has wrong type", func() {
--                              It("should return 'Unsupported Media Type'", 
func() {
--                                      resp, err := 
http.Post("http://localhost:4000/dns-query";, "application/text", 
bytes.NewReader([]byte("a")))
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusUnsupportedMediaType))
--                              })
--                      })
--                      When("Internal error occurs", func() {
--                              It("should return 'Internal server error'", 
func() {
--                                      msg := 
util.NewMsgWithQuestion("error.", A)
--                                      rawDNSMessage, err := msg.Pack()
--                                      Expect(err).Should(Succeed())
--
--                                      resp, err := 
http.Post("http://localhost:4000/dns-query";,
--                                              "application/dns-message", 
bytes.NewReader(rawDNSMessage))
--                                      Expect(err).Should(Succeed())
--                                      DeferCleanup(resp.Body.Close)
--
--                                      
Expect(resp).Should(HaveHTTPStatus(http.StatusInternalServerError))
--                              })
--                      })
--              })
--      })
--
--      Describe("Server create", func() {
--              var (
--                      cfg  config.Config
--                      cErr error
--              )
--              BeforeEach(func() {
--                      cErr = defaults.Set(&cfg)
--
--                      Expect(cErr).Should(Succeed())
--
--                      cfg.Upstreams.Groups = map[string][]config.Upstream{
--                              "default": {config.Upstream{Net: 
config.NetProtocolTcpUdp, Host: "1.1.1.1", Port: 53}},
--                      }
--
--                      cfg.Redis.Address = "test-fail"
--              })
--              When("Server is created", func() {
--                      It("is created without redis connection", func() {
--                              _, err := NewServer(&cfg)
--
--                              Expect(err).Should(Succeed())
--                      })
--                      It("can't be created if redis server is unavailable", 
func() {
--                              cfg.Redis.Required = true
--
--                              _, err := NewServer(&cfg)
--
--                              Expect(err).ShouldNot(Succeed())
--                      })
--              })
--      })
--
--      Describe("Server start", Label("XX"), func() {
--              When("Server start is called", func() {
--                      It("start was called 2 times, start should fail", 
func() {
--                              // create server
--                              server, err := NewServer(&config.Config{
--                                      Upstreams: config.UpstreamsConfig{
--                                              Groups: 
map[string][]config.Upstream{
--                                                      "default": 
{config.Upstream{Net: config.NetProtocolTcpUdp, Host: "4.4.4.4", Port: 53}},
--                                              },
--                                      },
--                                      CustomDNS: config.CustomDNSConfig{
--                                              Mapping: 
config.CustomDNSMapping{
--                                                      HostIPs: 
map[string][]net.IP{
--                                                              "custom.lan": 
{net.ParseIP("192.168.178.55")},
--                                                              "lan.home":   
{net.ParseIP("192.168.178.56")},
--                                                      },
--                                              },
--                                      },
--                                      Blocking: 
config.BlockingConfig{BlockType: "zeroIp"},
--                                      Ports: config.PortsConfig{
--                                              DNS: 
config.ListenConfig{":55556"},
--                                      },
--                              })
--
--                              Expect(err).Should(Succeed())
--
--                              errChan := make(chan error, 10)
--
--                              // start server
--                              go server.Start(errChan)
--
--                              DeferCleanup(server.Stop)
--
--                              Consistently(errChan, "1s").ShouldNot(Receive())
--
--                              // start again -> should fail
--                              server.Start(errChan)
--
--                              Eventually(errChan).Should(Receive())
--                      })
--              })
--      })
--      Describe("Server stop", func() {
--              When("Stop is called", func() {
--                      It("stop was called 2 times, start should fail", func() 
{
--                              // create server
--                              server, err := NewServer(&config.Config{
--                                      Upstreams: config.UpstreamsConfig{
--                                              Groups: 
map[string][]config.Upstream{
--                                                      "default": 
{config.Upstream{Net: config.NetProtocolTcpUdp, Host: "4.4.4.4", Port: 53}},
--                                              },
--                                      },
--                                      CustomDNS: config.CustomDNSConfig{
--                                              Mapping: 
config.CustomDNSMapping{
--                                                      HostIPs: 
map[string][]net.IP{
--                                                              "custom.lan": 
{net.ParseIP("192.168.178.55")},
--                                                              "lan.home":   
{net.ParseIP("192.168.178.56")},
--                                                      },
--                                              },
--                                      },
--                                      Blocking: 
config.BlockingConfig{BlockType: "zeroIp"},
--                                      Ports: config.PortsConfig{
--                                              DNS: 
config.ListenConfig{"127.0.0.1:55557"},
--                                      },
--                              })
--
--                              Expect(err).Should(Succeed())
--
--                              errChan := make(chan error, 10)
--
--                              // start server
--                              go func() {
--                                      server.Start(errChan)
--                              }()
--
--                              time.Sleep(100 * time.Millisecond)
--
--                              err = server.Stop()
--
--                              // stop server, should be ok
--                              Expect(err).Should(Succeed())
--
--                              // stop again, should raise error
--                              err = server.Stop()
--
--                              Expect(err).Should(HaveOccurred())
--                      })
--              })
--      })
--
--      Describe("NewServer with strict upstream strategy", func() {
--              It("successfully returns upstream branches", func() {
--                      branches, err := createUpstreamBranches(&config.Config{
--                              Upstreams: config.UpstreamsConfig{
--                                      Strategy: config.UpstreamStrategyStrict,
--                                      Groups: config.UpstreamGroups{
--                                              "default": {{Host: "0.0.0.0"}},
--                                      },
--                              },
--                      },
--                              nil)
--
--                      Expect(err).ToNot(HaveOccurred())
--                      Expect(branches).ToNot(BeNil())
--                      Expect(branches).To(HaveLen(1))
--                      _ = branches["default"].(*resolver.StrictResolver)
--              })
--      })
--
--      Describe("create query resolver", func() {
--              When("some upstream returns error", func() {
--                      It("create query resolver should return error", func() {
--                              r, err := createQueryResolver(&config.Config{
--                                      StartVerifyUpstream: true,
--                                      Upstreams: config.UpstreamsConfig{
--                                              Groups: config.UpstreamGroups{
--                                                      "default": {{Host: 
"0.0.0.0"}},
--                                              },
--                                      },
--                              },
--                                      nil, nil)
--
--                              Expect(err).To(HaveOccurred())
--                              
Expect(err).To(MatchError(ContainSubstring("creation of upstream branches 
failed: ")))
--                              Expect(r).To(BeNil())
--                      })
--              })
--      })
--
--      Describe("resolve client IP", func() {
--              Context("UDP address", func() {
--                      It("should correct resolve client IP", func() {
--                              ip, protocol := 
resolveClientIPAndProtocol(&net.UDPAddr{IP: net.ParseIP("192.168.178.88")})
--                              
Expect(ip).Should(Equal(net.ParseIP("192.168.178.88")))
--                              
Expect(protocol).Should(Equal(model.RequestProtocolUDP))
--                      })
--              })
--              Context("TCP address", func() {
--                      It("should correct resolve client IP", func() {
--                              ip, protocol := 
resolveClientIPAndProtocol(&net.TCPAddr{IP: net.ParseIP("192.168.178.88")})
--                              
Expect(ip).Should(Equal(net.ParseIP("192.168.178.88")))
--                              
Expect(protocol).Should(Equal(model.RequestProtocolTCP))
--                      })
--              })
--      })
--
--      Describe("self-signed certificate creation", func() {
--              var (
--                      cfg  config.Config
--                      cErr error
--              )
--              BeforeEach(func() {
--                      cErr = defaults.Set(&cfg)
--
--                      Expect(cErr).Should(Succeed())
--
--                      cfg.Upstreams.Groups = map[string][]config.Upstream{
--                              "default": {config.Upstream{Net: 
config.NetProtocolTcpUdp, Host: "1.1.1.1", Port: 53}},
--                      }
--              })
--
--              It("should create self-signed certificate if key/cert files are 
not provided", func() {
--                      cfg.KeyFile = ""
--                      cfg.CertFile = ""
--                      cfg.Ports = config.PortsConfig{
--                              HTTPS: []string{":14443"},
--                      }
--
--                      sut, err := NewServer(&cfg)
--                      Expect(err).Should(Succeed())
--                      Expect(sut.cert.Certificate).ShouldNot(BeNil())
--              })
--      })
--})
--
--func requestServer(request *dns.Msg) *dns.Msg {
--      conn, err := net.Dial("udp", ":55555")
--      if err != nil {
--              Log().Fatal("could not connect to server: ", err)
--      }
--      defer conn.Close()
--
--      msg, err := request.Pack()
--      if err != nil {
--              Log().Fatal("can't pack request: ", err)
--      }
--
--      _, err = conn.Write(msg)
--      if err != nil {
--              Log().Fatal("can't send request to server: ", err)
--      }
--
--      out := make([]byte, 1024)
--
--      if _, err := conn.Read(out); err == nil {
--              response := new(dns.Msg)
--
--              err = response.Unpack(out)
--
--              if err != nil {
--                      Log().Fatal("can't unpack response: ", err)
--              }
--
--              return response
--      }
--
--      Log().Fatal("could not read from connection", err)
--
--      return nil
--}
--
--func writeCertPem(tmpDir *TmpFolder) *TmpFile {
--      return tmpDir.CreateStringFile("cert.pem",
--              "-----BEGIN CERTIFICATE-----",
--              
"MIICMzCCAZygAwIBAgIRAJCCrDTGEtZfRpxDY1KAoswwDQYJKoZIhvcNAQELBQAw",
--              
"EjEQMA4GA1UEChMHQWNtZSBDbzAgFw03MDAxMDEwMDAwMDBaGA8yMDg0MDEyOTE2",
--              
"MDAwMFowEjEQMA4GA1UEChMHQWNtZSBDbzCBnzANBgkqhkiG9w0BAQEFAAOBjQAw",
--              
"gYkCgYEA4mEaF5yWYYrTfMgRXdBpgGnqsHIADQWlw7BIJWD/gNp+fgp4TUZ/7ggV",
--              
"rrvRORvRFjw14avd9L9EFP7XLi8ViU3uoE1UWI32MlrKqLbGNCXyUIApIoqlbRg6",
--              
"iErxIk5+ChzFuysQOx01S2yv/ML6dx7NOGHs1S38MUzRZtcXBH8CAwEAAaOBhjCB",
--              
"gzAOBgNVHQ8BAf8EBAMCAqQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/",
--              
"BAUwAwEB/zAdBgNVHQ4EFgQUslNI6tYIv909RttHaZVMS/u/VYYwLAYDVR0RBCUw",
--              
"I4IJbG9jYWxob3N0hwR/AAABhxAAAAAAAAAAAAAAAAAAAAABMA0GCSqGSIb3DQEB",
--              
"CwUAA4GBAJ2gRpQHr5Qj7dt26bYVMdN4JGXTsvjbVrJfKI0VfPGJ+SUY/uTVBUeX",
--              
"+Cwv4DFEPBlNx/lzuUkwmRaExC4/w81LWwxe5KltYsjyJuYowiUbLZ6tzLaQ9Bcx",
--              "jxClAVvgj90TGYOwsv6ESOX7GWteN1FlD3+jk7vefjFagaKKFYR9",
--              "-----END CERTIFICATE-----")
--}
--
--func writeKeyPem(tmpDir *TmpFolder) *TmpFile {
--      return tmpDir.CreateStringFile("key.pem",
--              "-----BEGIN PRIVATE KEY-----",
--              
"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOJhGheclmGK03zI",
--              
"EV3QaYBp6rByAA0FpcOwSCVg/4Dafn4KeE1Gf+4IFa670Tkb0RY8NeGr3fS/RBT+",
--              
"1y4vFYlN7qBNVFiN9jJayqi2xjQl8lCAKSKKpW0YOohK8SJOfgocxbsrEDsdNUts",
--              
"r/zC+ncezThh7NUt/DFM0WbXFwR/AgMBAAECgYEA1exixstPhI+2+OTrHFc1S4dL",
--              
"oz+ncqbSlZEBLGl0KWTQQfVM5+FmRR7Yto1/0lLKDBQL6t0J2x3fjWOhHmCaHKZA",
--              
"VAvZ8+OKxwofih3hlO0tGCB8szUJygp2FAmd0rOUqvPQ+PTohZEUXyDaB8MOIbX+",
--              
"qoo7g19+VlbyKqmM8HkCQQDs4GQJwEn7GXKllSMyOfiYnjQM2pwsqO0GivXkH+p3",
--              
"+h5KDp4g3O4EbmbrvZyZB2euVsBjW3pFMu+xPXuOXf91AkEA9KfC7LGLD2OtLmrM",
--              
"iCZAqHlame+uEEDduDmqjTPnNKUWVeRtYKMF5Hltbeo1jMXMSbVZ+fRWKfQ+HAhQ",
--              
"xjFJowJAV6U7PqRoe0FSO1QwXrA2fHnk9nCY4qlqckZObyckAVqJhIteFPjKFNeo",
--              
"u0dAPxsPUOGGc/zwA9Sx/ZmrMuUy1QJBALl7bqawO/Ng6G0mfwZBqgeQaYYHVnnw",
--              
"E6iV353J2eHpvzNDSUFYlyEOhk4soIindSf0m9CK08Be8a+jBkocF+0CQQC+Hi7L",
--              
"kZV1slpW82BxYIhs9Gb0OQgK8SsI4aQPTFGUarQXXAm4eRqBO0kaG+jGX6TtW353",
--              "EHK784GIxwVXKej/",
--              "-----END PRIVATE KEY-----")
--}
-diff --git a/resolver/hosts_file_resolver_test.go 
b/resolver/hosts_file_resolver_test.go
-deleted file mode 100644
-index eef4591..0000000
---- a/resolver/hosts_file_resolver_test.go
-+++ /dev/null
-@@ -1,376 +0,0 @@
--package resolver
--
--import (
--      "context"
--      "time"
--
--      "github.com/0xERR0R/blocky/config"
--      . "github.com/0xERR0R/blocky/helpertest"
--      "github.com/0xERR0R/blocky/log"
--      . "github.com/0xERR0R/blocky/model"
--      "github.com/miekg/dns"
--      . "github.com/onsi/ginkgo/v2"
--      . "github.com/onsi/gomega"
--      "github.com/stretchr/testify/mock"
--)
--
--var _ = Describe("HostsFileResolver", func() {
--      var (
--              TTL = uint32(time.Now().Second())
--
--              sut       *HostsFileResolver
--              sutConfig config.HostsFileConfig
--              m         *mockResolver
--              tmpDir    *TmpFolder
--              tmpFile   *TmpFile
--      )
--
--      Describe("Type", func() {
--              It("follows conventions", func() {
--                      expectValidResolverType(sut)
--              })
--      })
--
--      BeforeEach(func() {
--              tmpDir = NewTmpFolder("HostsFileResolver")
--              Expect(tmpDir.Error).Should(Succeed())
--              DeferCleanup(tmpDir.Clean)
--
--              tmpFile = writeHostFile(tmpDir)
--              Expect(tmpFile.Error).Should(Succeed())
--
--              sutConfig = config.HostsFileConfig{
--                      Sources:        config.NewBytesSources(tmpFile.Path),
--                      HostsTTL:       config.Duration(time.Duration(TTL) * 
time.Second),
--                      FilterLoopback: true,
--                      Loading: config.SourceLoadingConfig{
--                              RefreshPeriod:      -1,
--                              MaxErrorsPerSource: 5,
--                      },
--              }
--      })
--
--      JustBeforeEach(func() {
--              var err error
--
--              sut, err = NewHostsFileResolver(sutConfig, 
systemResolverBootstrap)
--              Expect(err).Should(Succeed())
--
--              m = &mockResolver{}
--              m.On("Resolve", mock.Anything).Return(&Response{Res: 
new(dns.Msg)}, nil)
--              sut.Next(m)
--      })
--
--      Describe("IsEnabled", func() {
--              It("is true", func() {
--                      Expect(sut.IsEnabled()).Should(BeTrue())
--              })
--      })
--
--      Describe("LogConfig", func() {
--              It("should log something", func() {
--                      logger, hook := log.NewMockEntry()
--
--                      sut.LogConfig(logger)
--
--                      Expect(hook.Calls).ShouldNot(BeEmpty())
--              })
--      })
--
--      Describe("Using hosts file", func() {
--              When("Hosts file cannot be located", func() {
--                      BeforeEach(func() {
--                              sutConfig = config.HostsFileConfig{
--                                      Sources:  
config.NewBytesSources("/this/file/does/not/exist"),
--                                      HostsTTL: 
config.Duration(time.Duration(TTL) * time.Second),
--                              }
--                      })
--                      It("should not parse any hosts", func() {
--                              Expect(sut.cfg.Sources).ShouldNot(BeEmpty())
--                              Expect(sut.hosts.v4.hosts).Should(BeEmpty())
--                              Expect(sut.hosts.v6.hosts).Should(BeEmpty())
--                              Expect(sut.hosts.v4.aliases).Should(BeEmpty())
--                              Expect(sut.hosts.v6.aliases).Should(BeEmpty())
--                              Expect(sut.hosts.isEmpty()).Should(BeTrue())
--                      })
--                      It("should go to next resolver on query", func() {
--                              Expect(sut.Resolve(newRequest("example.com.", 
A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
HaveResponseType(ResponseTypeRESOLVED),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                              ))
--                              m.AssertExpectations(GinkgoT())
--                      })
--              })
--
--              When("Hosts file is not set", func() {
--                      BeforeEach(func() {
--                              sutConfig.Deprecated.Filepath = 
new(config.BytesSource)
--                              sutConfig.Sources = nil
--
--                              m = &mockResolver{}
--                              m.On("Resolve", 
mock.Anything).Return(&Response{Res: new(dns.Msg)}, nil)
--                              sut.Next(m)
--                      })
--                      It("should not return an error", func() {
--                              err := sut.loadSources(context.Background())
--                              Expect(err).Should(Succeed())
--                      })
--                      It("should go to next resolver on query", func() {
--                              Expect(sut.Resolve(newRequest("example.com.", 
A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
HaveResponseType(ResponseTypeRESOLVED),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                              ))
--                              m.AssertExpectations(GinkgoT())
--                      })
--              })
--
--              When("Hosts file can be located", func() {
--                      It("should parse it successfully", func() {
--                              Expect(sut).ShouldNot(BeNil())
--                              Expect(sut.hosts.v4.hosts).Should(HaveLen(5))
--                              Expect(sut.hosts.v6.hosts).Should(HaveLen(2))
--                              Expect(sut.hosts.v4.aliases).Should(HaveLen(4))
--                              Expect(sut.hosts.v6.aliases).Should(HaveLen(2))
--                      })
--
--                      When("filterLoopback is false", func() {
--                              BeforeEach(func() {
--                                      sutConfig.FilterLoopback = false
--                              })
--
--                              It("should parse it successfully", func() {
--                                      Expect(sut).ShouldNot(BeNil())
--                                      
Expect(sut.hosts.v4.hosts).Should(HaveLen(7))
--                                      
Expect(sut.hosts.v6.hosts).Should(HaveLen(3))
--                                      
Expect(sut.hosts.v4.aliases).Should(HaveLen(5))
--                                      
Expect(sut.hosts.v6.aliases).Should(HaveLen(2))
--                              })
--                      })
--              })
--
--              When("Hosts file has too many errors", func() {
--                      BeforeEach(func() {
--                              tmpFile = 
tmpDir.CreateStringFile("hosts-too-many-errors.txt",
--                                      "invalidip localhost",
--                                      "127.0.0.1 localhost", // ok
--                                      "127.0.0.1 # no host",
--                                      "127.0.0.1 invalidhost!",
--                                      "a.b.c.d localhost",
--                                      "127.0.0.x localhost",
--                                      "256.0.0.1 localhost",
--                              )
--                              Expect(tmpFile.Error).Should(Succeed())
--
--                              sutConfig.Sources = 
config.NewBytesSources(tmpFile.Path)
--                      })
--
--                      It("should not be used", func() {
--                              Expect(sut).ShouldNot(BeNil())
--                              Expect(sut.cfg.Sources).ShouldNot(BeEmpty())
--                              Expect(sut.hosts.v4.hosts).Should(BeEmpty())
--                              Expect(sut.hosts.v6.hosts).Should(BeEmpty())
--                              Expect(sut.hosts.v4.aliases).Should(BeEmpty())
--                              Expect(sut.hosts.v6.aliases).Should(BeEmpty())
--                      })
--              })
--
--              When("IPv4 mapping is defined for a host", func() {
--                      It("defined ipv4 query should be resolved", func() {
--                              Expect(sut.Resolve(newRequest("ipv4host.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                                      
BeDNSRecord("ipv4host.", A, "192.168.2.1"),
--                                                      
HaveTTL(BeNumerically("==", TTL)),
--                                              ))
--                      })
--                      It("defined ipv4 query for alias should be resolved", 
func() {
--                              Expect(sut.Resolve(newRequest("router2.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                                      BeDNSRecord("router2.", 
A, "10.0.0.1"),
--                                                      
HaveTTL(BeNumerically("==", TTL)),
--                                              ))
--                      })
--                      It("ipv4 query should return NOERROR and empty result", 
func() {
--                              
Expect(sut.Resolve(newRequest("does.not.exist.", A))).
--                                      Should(
--                                              SatisfyAll(
--                                                      HaveNoAnswer(),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                                      
HaveResponseType(ResponseTypeRESOLVED),
--                                              ))
--                      })
--              })
--
--              When("IPv6 mapping is defined for a host", func() {
--                      It("defined ipv6 query should be resolved", func() {
--                              Expect(sut.Resolve(newRequest("ipv6host.", 
AAAA))).
--                                      Should(
--                                              SatisfyAll(
--                                                      
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                                      
BeDNSRecord("ipv6host.", AAAA, "faaf:faaf:faaf:faaf::1"),
--                                                      
HaveTTL(BeNumerically("==", TTL)),
--                                              ))
--                      })
--                      It("ipv6 query should return NOERROR and empty result", 
func() {
--                              
Expect(sut.Resolve(newRequest("does.not.exist.", AAAA))).
--                                      Should(
--                                              SatisfyAll(
--                                                      HaveNoAnswer(),
--                                                      
HaveReturnCode(dns.RcodeSuccess),
--                                                      
HaveResponseType(ResponseTypeRESOLVED),
--                                              ))
--                      })
--              })
--
--              When("the domain is not known", func() {
--                      It("calls the next resolver", func() {
--                              resp, err := 
sut.Resolve(newRequest("not-in-hostsfile.tld.", A))
--                              Expect(err).Should(Succeed())
--                              
Expect(resp).ShouldNot(HaveResponseType(ResponseTypeHOSTSFILE))
--                              m.AssertExpectations(GinkgoT())
--                      })
--              })
--
--              When("the question type is not handled", func() {
--                      It("calls the next resolver", func() {
--                              resp, err := 
sut.Resolve(newRequest("localhost.", MX))
--                              Expect(err).Should(Succeed())
--                              
Expect(resp).ShouldNot(HaveResponseType(ResponseTypeHOSTSFILE))
--                              m.AssertExpectations(GinkgoT())
--                      })
--              })
--
--              When("Reverse DNS request is received", func() {
--                      It("should resolve the defined domain name", func() {
--                              By("ipv4 with one hostname", func() {
--                                      
Expect(sut.Resolve(newRequest("2.0.0.10.in-addr.arpa.", PTR))).
--                                              Should(
--                                                      SatisfyAll(
--                                                              
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                              
HaveReturnCode(dns.RcodeSuccess),
--                                                              
BeDNSRecord("2.0.0.10.in-addr.arpa.", PTR, "router3."),
--                                                              
HaveTTL(BeNumerically("==", TTL)),
--                                                      ))
--                              })
--                              By("ipv4 with aliases", func() {
--                                      
Expect(sut.Resolve(newRequest("1.0.0.10.in-addr.arpa.", PTR))).
--                                              Should(
--                                                      SatisfyAll(
--                                                              
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                              
HaveReturnCode(dns.RcodeSuccess),
--                                                              
WithTransform(ToAnswer, ContainElements(
--                                                                      
BeDNSRecord("1.0.0.10.in-addr.arpa.", PTR, "router0."),
--                                                                      
BeDNSRecord("1.0.0.10.in-addr.arpa.", PTR, "router1."),
--                                                                      
BeDNSRecord("1.0.0.10.in-addr.arpa.", PTR, "router2."),
--                                                              )),
--                                                      ))
--                              })
--                              By("ipv6", func() {
--                                      
Expect(sut.Resolve(newRequest("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.f.a.a.f.f.a.a.f.f.a.a.f.f.a.a.f.ip6.arpa.",
 PTR))).
--                                              Should(
--                                                      SatisfyAll(
--                                                              
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                              
HaveReturnCode(dns.RcodeSuccess),
--                                                              
WithTransform(ToAnswer, ContainElements(
--                                                                      
BeDNSRecord("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.f.a.a.f.f.a.a.f.f.a.a.f.f.a.a.f.ip6.arpa.",
--                                                                              
PTR, "ipv6host."),
--                                                                      
BeDNSRecord("1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.f.a.a.f.f.a.a.f.f.a.a.f.f.a.a.f.ip6.arpa.",
--                                                                              
PTR, "ipv6host.local.lan."),
--                                                              )),
--                                                      ))
--                              })
--                      })
--
--                      It("should ignore invalid PTR", func() {
--                              resp, err := 
sut.Resolve(newRequest("2.0.0.10.in-addr.fail.arpa.", PTR))
--                              Expect(err).Should(Succeed())
--                              
Expect(resp).ShouldNot(HaveResponseType(ResponseTypeHOSTSFILE))
--                              m.AssertExpectations(GinkgoT())
--                      })
--
--                      When("filterLoopback is true", func() {
--                              It("calls the next resolver", func() {
--                                      resp, err := 
sut.Resolve(newRequest("1.0.0.127.in-addr.arpa.", PTR))
--                                      Expect(err).Should(Succeed())
--                                      
Expect(resp).ShouldNot(HaveResponseType(ResponseTypeHOSTSFILE))
--                                      m.AssertExpectations(GinkgoT())
--                              })
--                      })
--
--                      When("the IP is not known", func() {
--                              It("calls the next resolver", func() {
--                                      resp, err := 
sut.Resolve(newRequest("255.255.255.255.in-addr.arpa.", PTR))
--                                      Expect(err).Should(Succeed())
--                                      
Expect(resp).ShouldNot(HaveResponseType(ResponseTypeHOSTSFILE))
--                                      m.AssertExpectations(GinkgoT())
--                              })
--                      })
--
--                      When("filterLoopback is false", func() {
--                              BeforeEach(func() {
--                                      sutConfig.FilterLoopback = false
--                              })
--
--                              It("resolve the defined domain name", func() {
--                                      
Expect(sut.Resolve(newRequest("1.1.0.127.in-addr.arpa.", PTR))).
--                                              Should(
--                                                      SatisfyAll(
--                                                              
HaveResponseType(ResponseTypeHOSTSFILE),
--                                                              
HaveReturnCode(dns.RcodeSuccess),
--                                                              
WithTransform(ToAnswer, ContainElements(
--                                                                      
BeDNSRecord("1.1.0.127.in-addr.arpa.", PTR, "localhost2."),
--                                                                      
BeDNSRecord("1.1.0.127.in-addr.arpa.", PTR, "localhost2.local.lan."),
--                                                              )),
--                                                      ))
--                              })
--                      })
--              })
--      })
--
--      Describe("Delegating to next resolver", func() {
--              When("no hosts file is provided", func() {
--                      It("should delegate to next resolver", func() {
--                              _, err := 
sut.Resolve(newRequest("example.com.", A))
--                              Expect(err).Should(Succeed())
--                              // delegate was executed
--                              m.AssertExpectations(GinkgoT())
--                      })
--              })
--      })
--})
--
--func writeHostFile(tmpDir *TmpFolder) *TmpFile {
--      return tmpDir.CreateStringFile("hosts.txt",
--              "# Random comment",
--              "127.0.0.1               localhost",
--              "127.0.1.1               localhost2  localhost2.local.lan",
--              "::1                     localhost",
--              "# Two empty lines to follow",
--              "",
--              "",
--              "faaf:faaf:faaf:faaf::1  ipv6host    ipv6host.local.lan",
--              "192.168.2.1             ipv4host    ipv4host.local.lan",
--              "faaf:faaf:faaf:faaf::2  dualhost    dualhost.local.lan",
--              "192.168.2.2             dualhost    dualhost.local.lan",
--              "10.0.0.1                router0 router1 router2",
--              "10.0.0.2                router3     # Another comment",
--              "10.0.0.3                router4#comment without a space",
--              "10.0.0.4                            # Invalid entry",
--              "300.300.300.300         invalid4    # Invalid IPv4",
--              "abcd:efgh:ijkl::1       invalid6    # Invalid IPv6",
--              "1.2.3.4                 localhost", // localhost name but not 
localhost IP
--
--              // from 
https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts
--              "fe80::1%lo0             localhost", // interface name
--      )
--}

Reply via email to