Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #11 from mjorlitzky/doctests

Doctests
  • Loading branch information...
commit caa33facf8631b23e5fded0af1daeb4d36971d91 2 parents 5f5c324 + 8be25fc
@kazu-yamamoto authored
View
11 Doctests.hs
@@ -0,0 +1,11 @@
+module Main
+where
+
+import Test.DocTest
+import System.FilePath.Find ((==?), always, extension, find)
+
+find_sources :: IO [FilePath]
+find_sources = find always (extension ==? ".hs") "Network"
+
+main :: IO ()
+main = find_sources >>= doctest
View
42 Network/DNS.hs
@@ -1,29 +1,33 @@
-{-|
- Thread-safe DNS library written in Haskell.
-
- This code is written in Haskell, not using FFI.
-
- Sample code for DNS lookup:
-
-@
- import qualified Network.DNS as DNS (lookup)
- import Network.DNS hiding (lookup)
- main :: IO ()
- main = do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \\resolver -> do
- DNS.lookup resolver \"www.example.com\" A >>= print
-@
--}
-
+-- | The Network.DNS module re-exports all other exposed modules for
+-- convenience.
+--
+-- Applications will most likely use the high-level interface, while
+-- library/daemon authors may need to use the lower-level one.
+--
module Network.DNS (
-- * High level
module Network.DNS.Lookup
+ -- | The "Network.DNS.Lookup" module contains simple functions to
+ -- perform various DNS lookups. If you simply want to resolve a
+ -- hostname ('lookupA'), or find a domain's MX record
+ -- ('lookupMX'), this is the easiest way to do it.
+
, module Network.DNS.Resolver
+ -- | The "Network.DNS.Resolver" module is slightly more low-level
+ -- than "Network.DNS.Lookup". If you need to do something unusual,
+ -- you may need to use the 'lookup', 'lookupAuth', or 'lookupRaw'
+ -- functions.
+
, module Network.DNS.Types
+ -- | All of the types that the other modules use.
+
-- * Low level
, module Network.DNS.Decode
+ -- | Decoding a response.
+
, module Network.DNS.Encode
+ -- | Encoding a query.
+
) where
import Network.DNS.Lookup
@@ -31,5 +35,3 @@ import Network.DNS.Resolver
import Network.DNS.Types
import Network.DNS.Decode
import Network.DNS.Encode
-
-
View
293 Network/DNS/Lookup.hs
@@ -1,7 +1,62 @@
-{-|
- Upper level DNS lookup functions.
--}
-
+-- | Simple, high-level DNS lookup functions.
+--
+-- All of the lookup functions necessary run in IO, since they
+-- interact with the network. The return types are similar, but
+-- differ in what can be returned from a successful lookup.
+--
+-- We can think of the return type as \"either what I asked for, or
+-- an error\". For example, the 'lookupA' function, if successful,
+-- will return a list of 'IPv4'. The 'lookupMX' function will
+-- instead return a list of @('Domain',Int)@ pairs, where each pair
+-- represents a hostname and its associated priority.
+--
+-- The order of multiple results may not be consistent between
+-- lookups. If you require consistent results, apply
+-- 'Data.List.sort' to the returned list.
+--
+-- The errors that can occur are the same for all lookups. Namely:
+--
+-- * Timeout
+--
+-- * Wrong sequence number (foul play?)
+--
+-- * Unexpected data in the response
+--
+-- If an error occurs, you should be able to pattern match on the
+-- 'DNSError' constructor to determine which of these is the case.
+--
+-- /Note/: A result of \"no records\" is not considered an
+-- error. If you perform, say, an \'AAAA\' lookup for a domain with
+-- no such records, the \"success\" result would be @Right []@.
+--
+-- We perform a successful lookup of \"www.example.com\":
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "www.example.com"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupA resolver hostname
+-- Right [93.184.216.119]
+--
+-- The only error that we can easily cause is a timeout. We do this
+-- by creating and utilizing a 'ResolvConf' which has a timeout of
+-- one millisecond:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "www.example.com"
+-- >>> let badrc = defaultResolvConf { resolvTimeout = 1 }
+-- >>>
+-- >>> rs <- makeResolvSeed badrc
+-- >>> withResolver rs $ \resolver -> lookupA resolver hostname
+-- Left TimeoutExpired
+--
+-- As is the convention, successful results will always be wrapped
+-- in a 'Right', while errors will be wrapped in a 'Left'.
+--
+-- For convenience, you may wish to enable GHC's OverloadedStrings
+-- extension. This will allow you to avoid calling
+-- 'Data.ByteString.Char8.pack' on each domain name. See
+-- <http://www.haskell.org/ghc/docs/7.6.3/html/users_guide/type-class-extensions.html#overloaded-strings>
+-- for more information.
+--
module Network.DNS.Lookup (
lookupA, lookupAAAA
, lookupMX, lookupAviaMX, lookupAAAAviaMX
@@ -9,19 +64,37 @@ module Network.DNS.Lookup (
, lookupNSAuth
, lookupTXT
, lookupPTR
+ , lookupRDNS
, lookupSRV
) where
import Data.ByteString (ByteString)
+import qualified Data.ByteString.Char8 as BS (append, intercalate, pack, split)
import Data.IP
import Network.DNS.Resolver as DNS
import Network.DNS.Types
----------------------------------------------------------------
-{-|
- Resolving 'IPv4' by 'A'.
--}
+-- | Look up all \'A\' records for the given hostname.
+--
+-- A straightforward example:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "www.mew.org"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupA resolver hostname
+-- Right [202.232.15.101]
+--
+-- This function will also follow a CNAME and resolve its target if
+-- one exists for the queries hostname:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "www.kame.net"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupA resolver hostname
+-- Right [203.178.141.194]
+--
lookupA :: Resolver -> Domain -> IO (Either DNSError [IPv4])
lookupA rlv dom = do
erds <- DNS.lookup rlv dom A
@@ -34,9 +107,17 @@ lookupA rlv dom = do
unTag (RD_A x) = Right x
unTag _ = Left UnexpectedRDATA
-{-|
- Resolving 'IPv6' by 'AAAA'.
--}
+
+-- | Look up all (IPv6) \'AAAA\' records for the given hostname.
+--
+-- Examples:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "www.mew.org"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupAAAA resolver hostname
+-- Right [2001:240:11e:c00:00:00:00:101]
+--
lookupAAAA :: Resolver -> Domain -> IO (Either DNSError [IPv6])
lookupAAAA rlv dom = do
erds <- DNS.lookup rlv dom AAAA
@@ -51,9 +132,32 @@ lookupAAAA rlv dom = do
----------------------------------------------------------------
-{-|
- Resolving 'Domain' and its preference by 'MX'.
--}
+-- | Look up all \'MX\' records for the given hostname. Two parts
+-- constitute an MX record: a hostname , and an integer priority. We
+-- therefore return each record as a @('Domain', Int)@.
+--
+-- In this first example, we look up the MX for the domain
+-- \"example.com\". It has no MX (to prevent a deluge of spam from
+-- examples posted on the internet). But remember, \"no results\" is
+-- still a successful result.
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "example.com"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupMX resolver hostname
+-- Right []
+--
+-- The domain \"mew.org\" does however have a single MX:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "mew.org"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupMX resolver hostname
+-- Right [("mail.mew.org.",10)]
+--
+-- Also note that all hostnames are returned with a trailing dot to
+-- indicate the DNS root.
+--
lookupMX :: Resolver -> Domain -> IO (Either DNSError [(Domain,Int)])
lookupMX rlv dom = do
erds <- DNS.lookup rlv dom MX
@@ -66,15 +170,30 @@ lookupMX rlv dom = do
unTag (RD_MX pr dm) = Right (dm,pr)
unTag _ = Left UnexpectedRDATA
-{-|
- Resolving 'IPv4' by 'A' via 'MX'.
--}
+-- | Look up all \'MX\' records for the given hostname, and then
+-- resolve their hostnames to IPv4 addresses by calling
+-- 'lookupA'. The priorities are not retained.
+--
+-- Examples:
+--
+-- >>> import Data.List (sort)
+-- >>> let hostname = Data.ByteString.Char8.pack "mixi.jp"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> ips <- withResolver rs $ \resolver -> lookupAviaMX resolver hostname
+-- >>> fmap sort ips
+-- Right [202.32.29.4,202.32.29.5]
+--
+-- Since there is more than one result, it is necessary to sort the
+-- list in order to check for equality.
+--
lookupAviaMX :: Resolver -> Domain -> IO (Either DNSError [IPv4])
lookupAviaMX rlv dom = lookupXviaMX rlv dom (lookupA rlv)
-{-|
- Resolving 'IPv6' by 'AAAA' via 'MX'.
--}
+-- | Look up all \'MX\' records for the given hostname, and then
+-- resolve their hostnames to IPv6 addresses by calling
+-- 'lookupAAAA'. The priorities are not retained.
+--
lookupAAAAviaMX :: Resolver -> Domain -> IO (Either DNSError [IPv6])
lookupAAAAviaMX rlv dom = lookupXviaMX rlv dom (lookupAAAA rlv)
@@ -123,26 +242,71 @@ lookupNSImpl lookup_function rlv dom = do
unTag (RD_NS dm) = Right dm
unTag _ = Left UnexpectedRDATA
-{-|
- Resolving 'Domain' by 'NS'. Results taken from the ANSWER section of
- the response.
--}
+-- | Look up all \'NS\' records for the given hostname. The results
+-- are taken from the ANSWER section of the response (as opposed to
+-- AUTHORITY). For details, see e.g.
+-- <http://www.zytrax.com/books/dns/ch15/>.
+--
+-- There will typically be more than one name server for a
+-- domain. It is therefore extra important to sort the results if
+-- you prefer them to be at all deterministic.
+--
+-- Examples:
+--
+-- >>> import Data.List (sort)
+-- >>> let hostname = Data.ByteString.Char8.pack "mew.org"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> ns <- withResolver rs $ \resolver -> lookupNS resolver hostname
+-- >>> fmap sort ns
+-- Right ["ns1.mew.org.","ns2.mew.org."]
+--
lookupNS :: Resolver -> Domain -> IO (Either DNSError [Domain])
lookupNS = lookupNSImpl DNS.lookup
-{-|
- Resolving 'Domain' by 'NS'. Results taken from the AUTHORITY section
- of the response.
--}
+-- | Look up all \'NS\' records for the given hostname. The results
+-- are taken from the AUTHORITY section of the response and not the
+-- usual ANSWER (use 'lookupNS' for that). For details, see e.g.
+-- <http://www.zytrax.com/books/dns/ch15/>.
+--
+-- There will typically be more than one name server for a
+-- domain. It is therefore extra important to sort the results if
+-- you prefer them to be at all deterministic.
+--
+-- For an example, we can look up the nameservers for
+-- \"example.com\" from one of the root servers, a.gtld-servers.net,
+-- the IP address of which was found beforehand:
+--
+-- >>> import Data.List (sort)
+-- >>> let hostname = Data.ByteString.Char8.pack "example.com"
+-- >>>
+-- >>> let ri = RCHostName "192.5.6.30" -- a.gtld-servers.net
+-- >>> let rc = defaultResolvConf { resolvInfo = ri }
+-- >>> rs <- makeResolvSeed rc
+-- >>> ns <- withResolver rs $ \resolver -> lookupNSAuth resolver hostname
+-- >>> fmap sort ns
+-- Right ["a.iana-servers.net.","b.iana-servers.net."]
+--
lookupNSAuth :: Resolver -> Domain -> IO (Either DNSError [Domain])
lookupNSAuth = lookupNSImpl DNS.lookupAuth
----------------------------------------------------------------
-{-|
- Resolving 'String' by 'TXT'.
--}
+-- | Look up all \'TXT\' records for the given hostname. The results
+-- are free-form 'ByteString's.
+--
+-- Two common uses for \'TXT\' records are
+-- <http://en.wikipedia.org/wiki/Sender_Policy_Framework> and
+-- <http://en.wikipedia.org/wiki/DomainKeys_Identified_Mail>. As an
+-- example, we find the SPF record for \"mew.org\":
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "mew.org"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupTXT resolver hostname
+-- Right ["v=spf1 +mx -all"]
+--
lookupTXT :: Resolver -> Domain -> IO (Either DNSError [ByteString])
lookupTXT rlv dom = do
erds <- DNS.lookup rlv dom TXT
@@ -157,9 +321,21 @@ lookupTXT rlv dom = do
----------------------------------------------------------------
-{-|
- Resolving 'Domain' and its preference by 'PTR'.
--}
+-- | Look up all \'PTR\' records for the given hostname. To perform a
+-- reverse lookup on an IP address, you must first reverse its
+-- octets and then append the suffix \".in-addr.arpa.\"
+--
+-- We look up the PTR associated with the IP address
+-- 210.130.137.80, i.e., 80.137.130.210.in-addr.arpa:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "80.137.130.210.in-addr.arpa"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupPTR resolver hostname
+-- Right ["www-v4.iij.ad.jp."]
+--
+-- The 'lookupRDNS' function is more suited to this particular task.
+--
lookupPTR :: Resolver -> Domain -> IO (Either DNSError [Domain])
lookupPTR rlv dom = do
erds <- DNS.lookup rlv dom PTR
@@ -172,11 +348,56 @@ lookupPTR rlv dom = do
unTag (RD_PTR dm) = Right dm
unTag _ = Left UnexpectedRDATA
+
+-- | Convenient wrapper around 'lookupPTR' to perform a reverse lookup
+-- on a single IP address.
+--
+-- We repeat the example from 'lookupPTR', except now we pass the IP
+-- address directly:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "210.130.137.80"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupRDNS resolver hostname
+-- Right ["www-v4.iij.ad.jp."]
+--
+lookupRDNS :: Resolver -> Domain -> IO (Either DNSError [Domain])
+lookupRDNS rlv ip = lookupPTR rlv dom
+ where
+ -- ByteString constants.
+ dot = BS.pack "."
+ suffix = BS.pack ".in-addr.arpa"
+
+ octets = BS.split '.' ip
+ reverse_ip = BS.intercalate dot (reverse octets)
+ dom = reverse_ip `BS.append` suffix
+
----------------------------------------------------------------
-{-|
- Resolving 'Domain' and its preference by 'SRV'.
--}
+-- | Look up all \'SRV\' records for the given hostname. A SRV record
+-- comprises four fields,
+--
+-- * Priority (lower is more-preferred)
+--
+-- * Weight (relative frequency with which to use this record
+-- amongst all results with the same priority)
+--
+-- * Port (the port on which the service is offered)
+--
+-- * Target (the hostname on which the service is offered)
+--
+-- The first three are integral, and the target is another DNS
+-- hostname. We therefore return a four-tuple
+-- @(Int,Int,Int,'Domain')@.
+--
+-- Examples:
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "_sip._tcp.cisco.com"
+-- >>>
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookupSRV resolver hostname
+-- Right [(1,0,5060,"vcsgw.cisco.com.")]
+--
lookupSRV :: Resolver -> Domain -> IO (Either DNSError [(Int,Int,Int,Domain)])
lookupSRV rlv dom = do
erds <- DNS.lookup rlv dom SRV
View
127 Network/DNS/Resolver.hs
@@ -1,20 +1,5 @@
{-# LANGUAGE CPP #-}
-{-|
- DNS Resolver and lookup functions.
-
- Sample code:
-
-@
- import qualified Network.DNS as DNS (lookup)
- import Network.DNS hiding (lookup)
- main :: IO ()
- main = do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \\resolver -> do
- DNS.lookup resolver \"www.example.com\" A >>= print
-@
--}
-
+-- | DNS Resolver and generic (lower-level) lookup functions.
module Network.DNS.Resolver (
-- * Documentation
-- ** Configuration for resolver
@@ -49,15 +34,21 @@ import Control.Monad (when)
#endif
----------------------------------------------------------------
-{-|
- Union type for 'FilePath' and 'HostName'. Specify 'FilePath' to
- \"resolv.conf\" or numeric IP address in 'String' form.
--}
+
+-- | Union type for 'FilePath' and 'HostName'. Specify 'FilePath' to
+-- \"resolv.conf\" or numeric IP address in 'String' form.
+--
+-- /Warning/: Only numeric IP addresses are valid @RCHostName@s.
+--
+-- Example (using Google's public DNS cache):
+--
+-- >>> let cache = RCHostName "8.8.8.8"
+--
data FileOrNumericHost = RCFilePath FilePath | RCHostName HostName
-{-|
- Type for resolver configuration
--}
+
+-- | Type for resolver configuration. The easiest way to construct a
+-- @ResolvConf@ object is to modify the 'defaultResolvConf'.
data ResolvConf = ResolvConf {
resolvInfo :: FileOrNumericHost
, resolvTimeout :: Int
@@ -65,12 +56,20 @@ data ResolvConf = ResolvConf {
, resolvBufsize :: Integer
}
-{-|
- Default 'ResolvConf'.
- 'resolvInfo' is 'RCFilePath' \"\/etc\/resolv.conf\".
- 'resolvTimeout' is 3,000,000 micro seconds.
- 'resolvBufsize' is 512. (obsoleted)
--}
+
+-- | Return a default 'ResolvConf':
+--
+-- * 'resolvInfo' is 'RCFilePath' \"\/etc\/resolv.conf\".
+--
+-- * 'resolvTimeout' is 3,000,000 micro seconds.
+--
+-- * 'resolvBufsize' is 512. (obsoleted)
+--
+-- Example (use Google's public DNS cache instead of resolv.conf):
+--
+-- >>> let cache = RCHostName "8.8.8.8"
+-- >>> let rc = defaultResolvConf { resolvInfo = cache }
+--
defaultResolvConf :: ResolvConf
defaultResolvConf = ResolvConf {
resolvInfo = RCFilePath "/etc/resolv.conf"
@@ -101,9 +100,13 @@ data Resolver = Resolver {
----------------------------------------------------------------
-{-|
- Making 'ResolvSeed' from an IP address of a DNS cache server.
--}
+
+-- | Make a 'ResolvSeed' from a 'ResolvConf'.
+--
+-- Examples:
+--
+-- >>> rs <- makeResolvSeed defaultResolvConf
+--
makeResolvSeed :: ResolvConf -> IO ResolvSeed
makeResolvSeed conf = ResolvSeed <$> addr
<*> pure (resolvTimeout conf)
@@ -129,11 +132,10 @@ makeAddrInfo addr = do
----------------------------------------------------------------
-{-|
- Giving a thread-safe 'Resolver' to the function of the second
- argument. 'withResolver' should be passed to 'forkIO'.
--}
+-- | Giving a thread-safe 'Resolver' to the function of the second
+-- argument. 'withResolver' should be passed to 'forkIO'. For
+-- examples, see "Network.DNS.Lookup".
withResolver :: ResolvSeed -> (Resolver -> IO a) -> IO a
withResolver seed func = do
let ai = addrInfo seed
@@ -174,6 +176,14 @@ lookupSection section rlv dom typ = (>>= toRDATA) <$> lookupRaw rlv dom typ
-- | Look up resource records for a domain, collecting the results
-- from the ANSWER section of the response.
+--
+-- We repeat an example from "Network.DNS.Lookup":
+--
+-- >>> let hostname = Data.ByteString.Char8.pack "www.example.com"
+-- >>> rs <- makeResolvSeed defaultResolvConf
+-- >>> withResolver rs $ \resolver -> lookup resolver hostname A
+-- Right [93.184.216.119]
+--
lookup :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RDATA])
lookup = lookupSection answer
@@ -182,9 +192,48 @@ lookup = lookupSection answer
lookupAuth :: Resolver -> Domain -> TYPE -> IO (Either DNSError [RDATA])
lookupAuth = lookupSection authority
-{-|
- Looking up a domain and returning an entire DNS Response.
--}
+
+-- | Look up a name and return the entire DNS Response. Sample output
+-- is included below, however it is /not/ tested -- the sequence
+-- number is unpredictable (it has to be!).
+--
+-- The example code:
+--
+-- @
+-- let hostname = Data.ByteString.Char8.pack \"www.example.com\"
+-- rs <- makeResolvSeed defaultResolvConf
+-- withResolver rs $ \resolver -> lookupRaw resolver hostname A
+-- @
+--
+-- And the (formatted) expected output:
+--
+-- @
+-- Right (DNSFormat
+-- { header = DNSHeader
+-- { identifier = 1,
+-- flags = DNSFlags
+-- { qOrR = QR_Response,
+-- opcode = OP_STD,
+-- authAnswer = False,
+-- trunCation = False,
+-- recDesired = True,
+-- recAvailable = True,
+-- rcode = NoErr },
+-- qdCount = 1,
+-- anCount = 1,
+-- nsCount = 0,
+-- arCount = 0},
+-- question = [Question { qname = \"www.example.com.\",
+-- qtype = A}],
+-- answer = [ResourceRecord {rrname = \"www.example.com.\",
+-- rrtype = A,
+-- rrttl = 800,
+-- rdlen = 4,
+-- rdata = 93.184.216.119}],
+-- authority = [],
+-- additional = []})
+-- @
+--
lookupRaw :: Resolver -> Domain -> TYPE -> IO (Either DNSError DNSFormat)
lookupRaw rlv dom typ = do
seqno <- genId rlv
View
32 dns.cabal
@@ -5,7 +5,9 @@ Maintainer: Kazu Yamamoto <kazu@iij.ad.jp>
License: BSD3
License-File: LICENSE
Synopsis: DNS library in Haskell
-Description: DNS library for clients and servers.
+Description:
+ A thread-safe DNS library for both clients and servers written
+ in pure Haskell.
Category: Network
Cabal-Version: >= 1.10
Build-Type: Simple
@@ -86,6 +88,34 @@ Test-Suite spec
, network-conduit
, random
+-- The only dependencies we need to /build/ the doctest suite are
+-- base, doctest, and filemanip. If you want to be able to /run/ them,
+-- however, you're going to need the rest of the deps that might be
+-- used in the examples.
+Test-Suite doctests
+ Type: exitcode-stdio-1.0
+ Default-Language: Haskell2010
+ Hs-Source-Dirs: .
+ Ghc-Options: -Wall
+ Main-Is: Doctests.hs
+ Build-Depends: base
+ , attoparsec
+ , attoparsec-conduit
+ , binary
+ , blaze-builder
+ , bytestring
+ , conduit >= 0.5
+ , containers
+ , dns
+ , doctest >= 0.9
+ , filemanip == 0.3.*
+ , hspec
+ , iproute >= 1.2.4
+ , mtl
+ , network >= 2.3
+ , network-conduit
+ , random
+
Source-Repository head
Type: git
Location: git://github.com/kazu-yamamoto/dns.git
View
88 test2/LookupSpec.hs
@@ -2,37 +2,11 @@
module LookupSpec where
-import Control.Applicative
-import qualified Data.ByteString.Char8 as BS
-import Data.List
import Network.DNS as DNS
import Test.Hspec
spec :: Spec
spec = do
- describe "lookupA" $ do
- it "gets IPv4 addresses" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver ->
- DNS.lookupA resolver "www.mew.org"
- `shouldReturn`
- Right ["202.232.15.101"]
-
- it "gets IPv4 addresses via CNAME" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver ->
- DNS.lookupA resolver "www.kame.net"
- `shouldReturn`
- Right ["203.178.141.194"]
-
- it "returns TimeoutExpired on timeout" $ do
- -- Use a timeout of one millisecond.
- let badrc = defaultResolvConf { resolvTimeout = 1 }
- rs <- makeResolvSeed badrc
- withResolver rs $ \resolver ->
- DNS.lookupA resolver "www.example.com"
- `shouldReturn`
- Left TimeoutExpired
describe "lookupAAAA" $ do
it "gets IPv6 addresses" $ do
@@ -42,65 +16,3 @@ spec = do
`shouldReturn`
Right []
- DNS.lookupAAAA resolver "www.mew.org"
- `shouldReturn`
- Right ["2001:240:11e:c00::101"]
-
- describe "lookupNS" $ do
- it "gets NS" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver -> do
- actual <- DNS.lookupNS resolver "mew.org"
- let expected = Right ["ns1.mew.org.", "ns2.mew.org."]
- -- The order of NS records is variable, so we sort the
- -- result.
- sort <$> actual `shouldBe` expected
-
- describe "lookupNSAuth" $ do
- it "gets NS" $ do
- -- We expect the GTLD servers to return the NS in the
- -- AUTHORITY section of the response.
- let ri = RCHostName "192.5.6.30" -- a.gtld-servers.net
- let rc = defaultResolvConf { resolvInfo = ri }
- rs <- makeResolvSeed rc
- withResolver rs $ \resolver -> do
- actual <- DNS.lookupNSAuth resolver "example.com"
- let expected = Right ["a.iana-servers.net.",
- "b.iana-servers.net."]
- -- The order of NS records is variable, so we sort the
- -- result.
- sort <$> actual `shouldBe` expected
-
- describe "lookupTXT" $ do
- it "gets TXT" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver ->
- DNS.lookupTXT resolver "mew.org"
- `shouldReturn`
- Right ["v=spf1 +mx -all"]
-
- describe "lookupAviaMX" $ do
- it "gets IPv4 addresses via MX" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver -> do
- as <- DNS.lookupAviaMX resolver "mixi.jp"
- sort <$> as `shouldBe` Right ["202.32.29.4", "202.32.29.5"]
-
- describe "lookupPTR" $ do
- it "gets PTR" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver -> do
- let target = "210.130.137.80"
- rev = BS.intercalate "." (reverse (BS.split '.' target))
- `BS.append` ".in-addr.arpa"
- DNS.lookupPTR resolver rev
- `shouldReturn`
- Right ["www-v4.iij.ad.jp."]
-
- describe "lookupSRV" $ do
- it "gets SRV" $ do
- rs <- makeResolvSeed defaultResolvConf
- withResolver rs $ \resolver ->
- DNS.lookupSRV resolver "_sip._tcp.cisco.com"
- `shouldReturn`
- Right [(1,0,5060,"vcsgw.cisco.com.")]
Please sign in to comment.
Something went wrong with that request. Please try again.