an atproto pds written in F# (.NET 9) 馃
pds fsharp giraffe dotnet atproto
at main 7.5 kB view raw
1module MstTests 2 3open Xunit 4open PDSharp.Core 5open PDSharp.Core.Mst 6 7[<Fact>] 8let ``Serialization Roundtrip`` () = 9 let cid1 = Cid(Crypto.sha256Str "val1") 10 11 let e1 = { 12 PrefixLen = 0 13 KeySuffix = "apple" 14 Value = cid1 15 Tree = None 16 } 17 18 let e2 = { 19 PrefixLen = 2 20 KeySuffix = "ricot" 21 Value = cid1 22 Tree = None 23 } 24 25 let node = { Left = None; Entries = [ e1; e2 ] } 26 27 let bytes = Mst.serialize node 28 let node2 = Mst.deserialize bytes 29 30 Assert.Equal(node.Entries.Length, node2.Entries.Length) 31 Assert.Equal("apple", node2.Entries.[0].KeySuffix) 32 Assert.Equal("ricot", node2.Entries.[1].KeySuffix) 33 Assert.Equal(2, node2.Entries.[1].PrefixLen) 34 35[<Fact>] 36let ``Get Operation Linear Scan`` () = 37 let cid1 = Cid(Crypto.sha256Str "val1") 38 let cid2 = Cid(Crypto.sha256Str "val2") 39 40 let e1 = { 41 PrefixLen = 0 42 KeySuffix = "apple" 43 Value = cid1 44 Tree = None 45 } 46 47 let e2 = { 48 PrefixLen = 0 49 KeySuffix = "banana" 50 Value = cid2 51 Tree = None 52 } 53 54 let node = { Left = None; Entries = [ e1; e2 ] } 55 56 let loader (c : Cid) = async { return None } 57 58 let res1 = Mst.get loader node "apple" "" |> Async.RunSynchronously 59 Assert.Equal(Some cid1, res1) 60 61 let res2 = Mst.get loader node "banana" "" |> Async.RunSynchronously 62 Assert.Equal(Some cid2, res2) 63 64 let res3 = Mst.get loader node "cherry" "" |> Async.RunSynchronously 65 Assert.True(Option.isNone res3) 66 67[<Fact>] 68let ``Get Operation With Prefix Compression`` () = 69 let cid1 = Cid(Crypto.sha256Str "val1") 70 let cid2 = Cid(Crypto.sha256Str "val2") 71 72 let e1 = { 73 PrefixLen = 0 74 KeySuffix = "apple" 75 Value = cid1 76 Tree = None 77 } 78 79 let e2 = { 80 PrefixLen = 2 81 KeySuffix = "ricot" 82 Value = cid2 83 Tree = None 84 } 85 86 let node = { Left = None; Entries = [ e1; e2 ] } 87 let loader (c : Cid) = async { return None } 88 89 let res1 = Mst.get loader node "apricot" "" |> Async.RunSynchronously 90 Assert.Equal(Some cid2, res1) 91 92[<Fact>] 93let ``Put Operation Simple Insert`` () = 94 let store = System.Collections.Concurrent.ConcurrentDictionary<string, MstNode>() 95 96 let loader (c : Cid) = async { 97 let key = System.Convert.ToBase64String(c.Bytes) 98 let success, node = store.TryGetValue(key) 99 return if success then Some node else None 100 } 101 102 let persister (n : MstNode) = async { 103 let bytes = Mst.serialize n 104 let cid = Cid(Crypto.sha256 bytes) 105 let key = System.Convert.ToBase64String(cid.Bytes) 106 store.[key] <- n 107 return cid 108 } 109 110 let node = { Left = None; Entries = [] } 111 let cid1 = Cid(Crypto.sha256Str "v1") 112 let node2 = Mst.put loader persister node "apple" cid1 "" |> Async.RunSynchronously 113 114 Assert.Equal(1, node2.Entries.Length) 115 Assert.Equal("apple", node2.Entries.[0].KeySuffix) 116 Assert.Equal(0, node2.Entries.[0].PrefixLen) 117 Assert.Equal(cid1, node2.Entries.[0].Value) 118 119 let res = Mst.get loader node2 "apple" "" |> Async.RunSynchronously 120 Assert.Equal(Some cid1, res) 121 122[<Fact>] 123let ``Put Operation Multiple Sorted`` () = 124 let store = System.Collections.Concurrent.ConcurrentDictionary<string, MstNode>() 125 126 let loader (c : Cid) = async { 127 let key = System.Convert.ToBase64String(c.Bytes) 128 let success, node = store.TryGetValue(key) 129 return if success then Some node else None 130 } 131 132 let persister (n : MstNode) = async { 133 let bytes = Mst.serialize n 134 let cid = Cid(Crypto.sha256 bytes) 135 let key = System.Convert.ToBase64String(cid.Bytes) 136 store.[key] <- n 137 return cid 138 } 139 140 let mutable node = { Left = None; Entries = [] } 141 142 let k1, v1 = "apple", Cid(Crypto.sha256Str "1") 143 let k2, v2 = "banana", Cid(Crypto.sha256Str "2") 144 let k3, v3 = "cherry", Cid(Crypto.sha256Str "3") 145 146 node <- Mst.put loader persister node k1 v1 "" |> Async.RunSynchronously 147 node <- Mst.put loader persister node k2 v2 "" |> Async.RunSynchronously 148 node <- Mst.put loader persister node k3 v3 "" |> Async.RunSynchronously 149 150 let g1 = Mst.get loader node "apple" "" |> Async.RunSynchronously 151 let g2 = Mst.get loader node "banana" "" |> Async.RunSynchronously 152 let g3 = Mst.get loader node "cherry" "" |> Async.RunSynchronously 153 154 Assert.Equal(Some v1, g1) 155 Assert.Equal(Some v2, g2) 156 Assert.Equal(Some v3, g3) 157 158[<Fact>] 159let ``Put Operation Multiple Reverse`` () = 160 let store = System.Collections.Concurrent.ConcurrentDictionary<string, MstNode>() 161 162 let loader (c : Cid) = async { 163 let key = System.Convert.ToBase64String(c.Bytes) 164 let success, node = store.TryGetValue(key) 165 return if success then Some node else None 166 } 167 168 let persister (n : MstNode) = async { 169 let bytes = Mst.serialize n 170 let cid = Cid(Crypto.sha256 bytes) 171 let key = System.Convert.ToBase64String(cid.Bytes) 172 store.[key] <- n 173 return cid 174 } 175 176 let mutable node = { Left = None; Entries = [] } 177 178 let data = [ "zebra"; "yak"; "xylophone" ] 179 180 for k in data do 181 let v = Cid(Crypto.sha256Str k) 182 node <- Mst.put loader persister node k v "" |> Async.RunSynchronously 183 184 for k in data do 185 let expected = Cid(Crypto.sha256Str k) 186 let actual = Mst.get loader node k "" |> Async.RunSynchronously 187 Assert.Equal(Some expected, actual) 188 189[<Fact>] 190let ``Delete Operation Simple`` () = 191 let store = System.Collections.Concurrent.ConcurrentDictionary<string, MstNode>() 192 193 let loader (c : Cid) = async { 194 let key = System.Convert.ToBase64String(c.Bytes) 195 let success, node = store.TryGetValue(key) 196 return if success then Some node else None 197 } 198 199 let persister (n : MstNode) = async { 200 let bytes = Mst.serialize n 201 let cid = Cid(Crypto.sha256 bytes) 202 let key = System.Convert.ToBase64String(cid.Bytes) 203 store.[key] <- n 204 return cid 205 } 206 207 let mutable node = { Left = None; Entries = [] } 208 let cid1 = Cid(Crypto.sha256Str "val1") 209 210 node <- Mst.put loader persister node "apple" cid1 "" |> Async.RunSynchronously 211 212 let res1 = Mst.get loader node "apple" "" |> Async.RunSynchronously 213 Assert.Equal(Some cid1, res1) 214 215 // Delete 216 let nodeOpt = Mst.delete loader persister node "apple" "" |> Async.RunSynchronously 217 218 match nodeOpt with 219 | None -> () 220 | Some n -> 221 let res2 = Mst.get loader n "apple" "" |> Async.RunSynchronously 222 Assert.True(Option.isNone res2) 223 224[<Fact>] 225let ``Determinism From Entries`` () = 226 let store = System.Collections.Concurrent.ConcurrentDictionary<string, MstNode>() 227 228 let loader (c : Cid) = async { 229 let key = System.Convert.ToBase64String(c.Bytes) 230 let success, node = store.TryGetValue(key) 231 return if success then Some node else None 232 } 233 234 let persister (n : MstNode) = async { 235 let bytes = Mst.serialize n 236 let cid = Cid(Crypto.sha256 bytes) 237 let key = System.Convert.ToBase64String(cid.Bytes) 238 store.[key] <- n 239 return cid 240 } 241 242 let data = [ 243 "apple", Cid(Crypto.sha256Str "1") 244 "banana", Cid(Crypto.sha256Str "2") 245 "cherry", Cid(Crypto.sha256Str "3") 246 "date", Cid(Crypto.sha256Str "4") 247 "elderberry", Cid(Crypto.sha256Str "5") 248 ] 249 250 251 let node1 = Mst.fromEntries loader persister data |> Async.RunSynchronously 252 let cid1 = persister node1 |> Async.RunSynchronously 253 254 let node2 = 255 Mst.fromEntries loader persister (List.rev data) |> Async.RunSynchronously 256 257 let cid2 = persister node2 |> Async.RunSynchronously 258 let data3 = [ data.[2]; data.[0]; data.[4]; data.[1]; data.[3] ] 259 let node3 = Mst.fromEntries loader persister data3 |> Async.RunSynchronously 260 let cid3 = persister node3 |> Async.RunSynchronously 261 262 Assert.Equal(cid1, cid2) 263 Assert.Equal(cid1, cid3) 264 ()