forked from schmittlauch/Hash2Pub
NodeCache: add entries
+ tests
This commit is contained in:
parent
8d9697c1ef
commit
aed80263a7
|
@ -17,6 +17,7 @@ module Hash2Pub.FediChord (
|
||||||
, NodeCache
|
, NodeCache
|
||||||
, CacheEntry
|
, CacheEntry
|
||||||
, cacheGetNodeStateUnvalidated
|
, cacheGetNodeStateUnvalidated
|
||||||
|
, addCacheEntry
|
||||||
, genNodeID
|
, genNodeID
|
||||||
, genNodeIDBS
|
, genNodeIDBS
|
||||||
, genKeyID
|
, genKeyID
|
||||||
|
@ -26,7 +27,7 @@ module Hash2Pub.FediChord (
|
||||||
|
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import Network.Socket
|
import Network.Socket
|
||||||
import Data.Time.Clock.System
|
import Data.Time.Clock
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
|
|
||||||
-- for hashing and ID conversion
|
-- for hashing and ID conversion
|
||||||
|
@ -127,9 +128,21 @@ type NodeCache = Map.Map NodeID CacheEntry
|
||||||
type CacheEntry = (
|
type CacheEntry = (
|
||||||
Bool
|
Bool
|
||||||
, NodeState
|
, NodeState
|
||||||
, SystemTime
|
, UTCTime
|
||||||
) -- ^ ( a node's validation status, data, timestamp for cache entry expiration )
|
) -- ^ ( a node's validation status, data, timestamp for cache entry expiration )
|
||||||
|
|
||||||
|
addCacheEntry :: NodeState -> Integer -> NodeCache -> IO NodeCache
|
||||||
|
addCacheEntry node diffSeconds cache = do
|
||||||
|
now <- getCurrentTime
|
||||||
|
let
|
||||||
|
-- TODO: limit diffSeconds to some maximum value to prevent malicious nodes from inserting entries valid nearly until eternity
|
||||||
|
timestamp = fromInteger (negate diffSeconds) `addUTCTime` now
|
||||||
|
newCache = Map.insert (nid node) (False, node, timestamp) cache
|
||||||
|
return newCache
|
||||||
|
|
||||||
|
-- clean up cache entries: once now - entry > maxAge
|
||||||
|
-- transfer difference now - entry to other node
|
||||||
|
|
||||||
-- | return the @NodeState@ data from a cache entry without checking its validation status
|
-- | return the @NodeState@ data from a cache entry without checking its validation status
|
||||||
cacheGetNodeStateUnvalidated :: CacheEntry -> NodeState
|
cacheGetNodeStateUnvalidated :: CacheEntry -> NodeState
|
||||||
cacheGetNodeStateUnvalidated (_, nState, _) = nState
|
cacheGetNodeStateUnvalidated (_, nState, _) = nState
|
||||||
|
|
|
@ -11,12 +11,6 @@ import Hash2Pub.FediChord
|
||||||
|
|
||||||
spec :: Spec
|
spec :: Spec
|
||||||
spec = do
|
spec = do
|
||||||
-- define some sensible test data
|
|
||||||
let
|
|
||||||
nodeDomain = "example.social"
|
|
||||||
vs = 4
|
|
||||||
ip = tupleToHostAddress6 (0x2001, 0x16b8, 0x755a, 0xb110, 0x7d6a, 0x12ab, 0xf0c5, 0x386e)
|
|
||||||
|
|
||||||
describe "NodeID" $ do
|
describe "NodeID" $ do
|
||||||
it "can store a numeral ID" $
|
it "can store a numeral ID" $
|
||||||
getNodeID (toNodeID 2342) `shouldBe` 2342
|
getNodeID (toNodeID 2342) `shouldBe` 2342
|
||||||
|
@ -36,8 +30,8 @@ spec = do
|
||||||
it "throws an exception when @toNodeID@ on out-of-bound values"
|
it "throws an exception when @toNodeID@ on out-of-bound values"
|
||||||
pending
|
pending
|
||||||
it "can be generated" $ do
|
it "can be generated" $ do
|
||||||
genNodeIDBS ip nodeDomain vs `shouldBe` "\ACK\211\183&S\GS\214\247Xn8\216\232\195\247\162\182\253\210\SOHG7I\194\251\196\130\142RSx\219"
|
genNodeIDBS exampleIp exampleNodeDomain exampleVs `shouldBe` "\ACK\211\183&S\GS\214\247Xn8\216\232\195\247\162\182\253\210\SOHG7I\194\251\196\130\142RSx\219"
|
||||||
genNodeID ip nodeDomain vs `shouldBe` toNodeID 3087945874980469002564169693112490135217795916629034079089428181202645514459
|
genNodeID exampleIp exampleNodeDomain exampleVs `shouldBe` toNodeID 3087945874980469002564169693112490135217795916629034079089428181202645514459
|
||||||
|
|
||||||
describe "ByteString to Integer conversion" $
|
describe "ByteString to Integer conversion" $
|
||||||
it "correctly interprets ByteStrings as unsigned big-endian integers" $ do
|
it "correctly interprets ByteStrings as unsigned big-endian integers" $ do
|
||||||
|
@ -51,27 +45,13 @@ spec = do
|
||||||
genKeyID "#sometag" `shouldBe` 80934974700514031200587628522801847528706765451025022694022301350330549806700
|
genKeyID "#sometag" `shouldBe` 80934974700514031200587628522801847528706765451025022694022301350330549806700
|
||||||
genKeyID "#ÄปӥicоdeTag" `shouldBe` 5709825004658123480531764908635278432808461265905814952223156184506818894505
|
genKeyID "#ÄปӥicоdeTag" `shouldBe` 5709825004658123480531764908635278432808461265905814952223156184506818894505
|
||||||
describe "NodeState" $ do
|
describe "NodeState" $ do
|
||||||
it "can be initialised" $ do
|
it "can be initialised" $
|
||||||
let ns = NodeState {
|
print exampleNodeState
|
||||||
nid = toNodeID 12
|
|
||||||
, domain = nodeDomain
|
|
||||||
, ipAddr = ip
|
|
||||||
, dhtPort = 2342
|
|
||||||
, apPort = Nothing
|
|
||||||
, nodeCache = Map.empty
|
|
||||||
, successors = []
|
|
||||||
, predecessors = []
|
|
||||||
, kNeighbours = 3
|
|
||||||
, lNumBestNodes = 3
|
|
||||||
, pNumParallelQueries = 2
|
|
||||||
, jEntriesPerSlice = 2
|
|
||||||
}
|
|
||||||
print ns
|
|
||||||
it "can be initialised partly and then modified later" $ do
|
it "can be initialised partly and then modified later" $ do
|
||||||
let ns = NodeState {
|
let ns = NodeState {
|
||||||
nid = undefined
|
nid = undefined
|
||||||
, domain = nodeDomain
|
, domain = exampleNodeDomain
|
||||||
, ipAddr = ip
|
, ipAddr = exampleIp
|
||||||
, dhtPort = 2342
|
, dhtPort = 2342
|
||||||
, apPort = Nothing
|
, apPort = Nothing
|
||||||
, nodeCache = Map.empty
|
, nodeCache = Map.empty
|
||||||
|
@ -86,4 +66,37 @@ spec = do
|
||||||
nid = genNodeID (ipAddr ns) (domain ns) 3
|
nid = genNodeID (ipAddr ns) (domain ns) 3
|
||||||
}
|
}
|
||||||
print nsReady
|
print nsReady
|
||||||
|
describe "NodeCache" $ do
|
||||||
|
it "entries can be added to a node cache" $ do
|
||||||
|
let
|
||||||
|
emptyCache = nodeCache exampleNodeState
|
||||||
|
anotherNode = exampleNodeState { nid = (toNodeID 2^(23::Integer)+1)}
|
||||||
|
newCache <- addCacheEntry exampleNodeState 0 =<< addCacheEntry anotherNode 10 emptyCache
|
||||||
|
Map.size newCache `shouldBe` 2
|
||||||
|
|
||||||
|
-- some example data
|
||||||
|
|
||||||
|
exampleNodeState :: NodeState
|
||||||
|
exampleNodeState = NodeState {
|
||||||
|
nid = toNodeID 12
|
||||||
|
, domain = exampleNodeDomain
|
||||||
|
, ipAddr = exampleIp
|
||||||
|
, dhtPort = 2342
|
||||||
|
, apPort = Nothing
|
||||||
|
, nodeCache = Map.empty
|
||||||
|
, successors = []
|
||||||
|
, predecessors = []
|
||||||
|
, kNeighbours = 3
|
||||||
|
, lNumBestNodes = 3
|
||||||
|
, pNumParallelQueries = 2
|
||||||
|
, jEntriesPerSlice = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
exampleNodeDomain :: String
|
||||||
|
exampleNodeDomain = "example.social"
|
||||||
|
exampleVs :: (Integral i) => i
|
||||||
|
exampleVs = 4
|
||||||
|
exampleIp :: HostAddress6
|
||||||
|
exampleIp = tupleToHostAddress6 (0x2001, 0x16b8, 0x755a, 0xb110, 0x7d6a, 0x12ab, 0xf0c5, 0x386e)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue