ligo/test/shell/test_store.ml

442 lines
15 KiB
OCaml
Raw Normal View History

2016-10-12 17:00:19 +04:00
(**************************************************************************)
(* *)
2017-11-14 03:36:14 +04:00
(* Copyright (c) 2014 - 2017. *)
2016-10-12 17:00:19 +04:00
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
2016-09-08 21:13:10 +04:00
open Error_monad
2016-09-08 21:13:10 +04:00
open Hash
open Store
let (>>=) = Lwt.bind
let (>|=) = Lwt.(>|=)
let (//) = Filename.concat
(** Basic blocks *)
let genesis_block =
Block_hash.of_b58check_exn
"BLockGenesisGenesisGenesisGenesisGenesisGeneskvg68z"
2016-09-08 21:13:10 +04:00
let genesis_protocol =
Protocol_hash.of_b58check_exn
"ProtoDemoDemoDemoDemoDemoDemoDemoDemoDemoDemoD3c8k9"
2016-09-08 21:13:10 +04:00
let genesis_time =
Time.of_seconds 0L
let genesis = {
State.Net.time = genesis_time ;
2016-09-08 21:13:10 +04:00
block = genesis_block ;
protocol = genesis_protocol ;
}
(** *)
let wrap_store_init f base_dir =
let root = base_dir // "store" in
Store.init root >>= function
2017-03-07 12:51:11 +04:00
| Ok store ->
f store >>= fun () ->
return ()
| Error err ->
Format.kasprintf Pervasives.failwith
"@[Cannot initialize store:@ %a@]" pp_print_error err
let wrap_raw_store_init f base_dir =
let root = base_dir // "store" in
Raw_store.init root >>= function
2017-03-07 12:51:11 +04:00
| Ok store ->
f store >>= fun () ->
return ()
| Error err ->
Format.kasprintf Pervasives.failwith
"@[Cannot initialize store:@ %a@]" pp_print_error err
2016-09-08 21:13:10 +04:00
let test_init _ = Lwt.return_unit
2017-03-31 15:04:05 +04:00
let net_id = Net_id.of_block_hash genesis_block
2016-09-08 21:13:10 +04:00
(** Operation store *)
let make proto : Tezos_data.Operation.t =
{ shell = { branch = genesis_block } ; proto }
2016-09-08 21:13:10 +04:00
let op1 = make (MBytes.of_string "Capadoce")
let oph1 = Tezos_data.Operation.hash op1
2016-09-08 21:13:10 +04:00
let op2 = make (MBytes.of_string "Kivu")
let oph2 = Tezos_data.Operation.hash op2
2016-09-08 21:13:10 +04:00
(** Block store *)
let lolblock ?(operations = []) header =
let operations_hash =
Operation_list_list_hash.compute
[Operation_list_hash.compute operations] in
{ Store.Block.header =
{ Block_header.shell =
{ timestamp = Time.of_seconds (Random.int64 1500L) ;
level = 0l ; (* dummy *)
proto_level = 0 ; (* dummy *)
validation_passes = Random.int 32 ;
predecessor = genesis_block ; operations_hash ;
fitness = [MBytes.of_string @@ string_of_int @@ String.length header;
MBytes.of_string @@ string_of_int @@ 12] } ;
proto = MBytes.of_string header ;
} ;
max_operations_ttl = 0 ;
message = "" ;
2017-07-17 17:59:09 +04:00
context = Context.dummy_commit ;
max_number_of_operations = [] ;
max_operation_data_length = 0 ;
2016-09-08 21:13:10 +04:00
}
let b1 = lolblock "Blop !"
let bh1 = Block_header.hash b1.header
2016-09-08 21:13:10 +04:00
let b2 = lolblock "Tacatlopo"
let bh2 = Block_header.hash b2.header
2016-09-08 21:13:10 +04:00
let b3 = lolblock ~operations:[oph1;oph2] "Persil"
let bh3 = Block_header.hash b3.header
2016-10-06 20:30:04 +04:00
let bh3' =
let raw = Bytes.of_string @@ Block_hash.to_string bh3 in
2016-10-06 20:30:04 +04:00
Bytes.set raw 31 '\000' ;
Bytes.set raw 30 '\000' ;
Block_hash.of_string_exn @@ Bytes.to_string raw
2016-09-08 21:13:10 +04:00
let equal (b1: Store.Block.contents) (b2: Store.Block.contents) =
Block_header.equal b1.header b2.header &&
b1.message = b2.message
2016-09-08 21:13:10 +04:00
let check_block s h b =
Store.Block.Contents.read (s, h) >>= function
| Ok b' when equal b b' -> Lwt.return_unit
| Ok _ ->
2016-09-08 21:13:10 +04:00
Printf.eprintf "Error while reading block %s\n%!" (Block_hash.to_hex h);
exit 1
| Error err ->
Format.eprintf "@[Error while reading block %s:@ %a\n@]"
(Block_hash.to_hex h)
pp_print_error err;
2016-09-08 21:13:10 +04:00
exit 1
let test_block s =
let s = Store.Net.get s net_id in
let s = Store.Block.get s in
Block.Contents.store (s, bh1) b1 >>= fun () ->
Block.Contents.store (s, bh2) b2 >>= fun () ->
Block.Contents.store (s, bh3) b3 >>= fun () ->
check_block s bh1 b1 >>= fun () ->
check_block s bh2 b2 >>= fun () ->
check_block s bh3 b3
let test_expand s =
let s = Store.Net.get s net_id in
let s = Store.Block.get s in
Block.Contents.store (s, bh1) b1 >>= fun () ->
Block.Contents.store (s, bh2) b2 >>= fun () ->
Block.Contents.store (s, bh3) b3 >>= fun () ->
Block.Contents.store (s, bh3') b3 >>= fun () ->
Base58.complete (Block_hash.to_short_b58check bh1) >>= fun res ->
Assert.equal_string_list ~msg:__LOC__ res [Block_hash.to_b58check bh1] ;
Base58.complete (Block_hash.to_short_b58check bh2) >>= fun res ->
Assert.equal_string_list ~msg:__LOC__ res [Block_hash.to_b58check bh2] ;
Base58.complete (Block_hash.to_short_b58check bh3) >>= fun res ->
Assert.equal_string_list ~msg:__LOC__
(List.sort String.compare res)
[Block_hash.to_b58check bh3' ; Block_hash.to_b58check bh3] ;
Lwt.return_unit
2016-10-06 20:30:04 +04:00
2016-09-08 21:13:10 +04:00
(** Generic store *)
let check (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) k d =
Store.read_opt s k >|= fun d' ->
2016-09-08 21:13:10 +04:00
if d' <> Some d then begin
Assert.fail_msg
"Error while reading key %S\n%!" (String.concat Filename.dir_sep k) ;
2016-09-08 21:13:10 +04:00
end
let check_none (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) k =
Store.read_opt s k >|= function
2016-09-08 21:13:10 +04:00
| None -> ()
| Some _ ->
Assert.fail_msg
2016-09-08 21:13:10 +04:00
"Error while reading non-existent key %S\n%!"
(String.concat Filename.dir_sep k)
let test_generic (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) =
Store.store s ["day";"current"] (MBytes.of_string "Mercredi") >>= fun () ->
Store.store s ["day";"next"] (MBytes.of_string "Jeudi") >>= fun () ->
Store.store s ["day";"truc";"chose"] (MBytes.of_string "Vendredi") >>= fun () ->
check (module Store) s ["day";"current"] (MBytes.of_string "Mercredi") >>= fun () ->
check (module Store) s ["day";"next"] (MBytes.of_string "Jeudi") >>= fun () ->
check_none (module Store) s ["day"]
let list (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) k =
Store.fold_keys s k ~init:[] ~f:(fun k acc -> Lwt.return (k :: acc))
let test_generic_list (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) =
Store.store s ["a"; "b"] (MBytes.of_string "Novembre") >>= fun () ->
Store.store s ["a"; "c"] (MBytes.of_string "Juin") >>= fun () ->
Store.store s ["a"; "d"; "e"] (MBytes.of_string "Septembre") >>= fun () ->
Store.store s ["f";] (MBytes.of_string "Avril") >>= fun () ->
Store.store s ["g"; "h"] (MBytes.of_string "Avril") >>= fun () ->
list (module Store) s [] >>= fun l ->
2017-04-05 20:24:26 +04:00
Assert.equal_string_list_list ~msg:__LOC__
[["a";"b"];["a";"c"];["a";"d";"e"];["f"];["g";"h"]]
(List.sort compare l) ;
list (module Store) s ["a"] >>= fun l ->
2017-04-05 20:24:26 +04:00
Assert.equal_string_list_list
~msg:__LOC__ [["a";"b"]; ["a";"c"]; ["a";"d";"e"]]
(List.sort compare l) ;
list (module Store) s ["f"] >>= fun l ->
2017-04-05 20:24:26 +04:00
Assert.equal_string_list_list ~msg:__LOC__ [] l ;
list (module Store) s ["g"] >>= fun l ->
2017-04-05 20:24:26 +04:00
Assert.equal_string_list_list ~msg:__LOC__ [["g";"h"]] (List.sort compare l) ;
list (module Store) s ["i"] >>= fun l ->
2017-04-05 20:24:26 +04:00
Assert.equal_string_list_list ~msg:__LOC__ [] l ;
Lwt.return_unit
2016-09-08 21:13:10 +04:00
(** HashSet *)
open Store_helpers
let test_hashset (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) =
let module BlockSet = Block_hash.Set in
2016-09-08 21:13:10 +04:00
let module StoreSet =
Make_buffered_set
(Make_substore(Store)(struct let name = ["test_set"] end))
(Block_hash)
(BlockSet) in
let bhset : BlockSet.t = BlockSet.add bh2 (BlockSet.add bh1 BlockSet.empty) in
StoreSet.store_all s bhset >>= fun () ->
StoreSet.read_all s >>= fun bhset' ->
Assert.equal_block_set ~msg:__LOC__ bhset bhset' ;
let bhset2 =
Pervasives.(bhset |> BlockSet.add bh3 |> BlockSet.remove bh1) in
StoreSet.store_all s bhset2 >>= fun () ->
StoreSet.read_all s >>= fun bhset2' ->
Assert.equal_block_set ~msg:__LOC__ bhset2 bhset2' ;
2017-11-13 17:29:28 +04:00
StoreSet.fold s ~init:BlockSet.empty
~f:(fun bh acc -> Lwt.return (BlockSet.add bh acc)) >>= fun bhset2'' ->
Assert.equal_block_set ~msg:__LOC__ bhset2 bhset2'' ;
Store.store s ["day";"current"] (MBytes.of_string "Mercredi") >>= fun () ->
StoreSet.remove_all s >>= fun () ->
StoreSet.read_all s >>= fun empty ->
Assert.equal_block_set ~msg:__LOC__ BlockSet.empty empty ;
check (module Store) s ["day";"current"] (MBytes.of_string "Mercredi") >>= fun () ->
Lwt.return_unit
2016-09-08 21:13:10 +04:00
(** HashMap *)
let test_hashmap (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) =
let module BlockMap = Block_hash.Map in
2016-09-08 21:13:10 +04:00
let module StoreMap =
Make_buffered_map
(Make_substore(Store)(struct let name = ["test_map"] end))
(Block_hash)
(Make_value(struct
type t = int * char
let encoding =
Data_encoding.(tup2 int31 (conv int_of_char char_of_int int8))
end))
2016-09-08 21:13:10 +04:00
(BlockMap) in
let eq = (=) in
2016-09-08 21:13:10 +04:00
let map =
Pervasives.(BlockMap.empty |>
BlockMap.add bh1 (1, 'a') |> BlockMap.add bh2 (2, 'b')) in
StoreMap.store_all s map >>= fun () ->
StoreMap.read_all s >>= fun map' ->
Assert.equal_block_map ~msg:__LOC__ ~eq map map' ;
let map2 =
Pervasives.(map |> BlockMap.add bh3 (3, 'c') |> BlockMap.remove bh1) in
StoreMap.store_all s map2 >>= fun () ->
StoreMap.read_all s >>= fun map2' ->
Assert.equal_block_map ~msg:__LOC__ ~eq map2 map2' ;
Lwt.return_unit
(** Functors *)
let test_single (type t)
(module Store: Store_sigs.STORE with type t = t) (s: Store.t) =
let module Single =
Make_single_store
(Store)
(struct let name = ["plop"] end)
(Make_value(struct
type t = int * string
let encoding = Data_encoding.(tup2 int31 string)
end)) in
Single.known s >>= fun known ->
Assert.is_false ~msg:__LOC__ known ;
Single.read_opt s >>= fun v' ->
Assert.equal ~msg:__LOC__ None v' ;
let v = (3, "Non!") in
Single.store s v >>= fun () ->
Single.known s >>= fun known ->
Assert.is_true ~msg:__LOC__ known ;
Single.read_opt s >>= fun v' ->
Assert.equal ~msg:__LOC__ (Some v) v' ;
2017-04-05 20:24:26 +04:00
Single.remove s >>= fun () ->
Single.known s >>= fun known ->
Assert.is_false ~msg:__LOC__ known ;
Single.read_opt s >>= fun v' ->
Assert.equal ~msg:__LOC__ None v' ;
Lwt.return_unit
module Sub =
Make_substore(Raw_store)(struct let name = ["plop";"plip"] end)
module SubBlocks =
Make_indexed_substore
(Make_substore(Raw_store)(struct let name = ["blocks"] end))
(Block_hash)
module SubBlocksSet =
SubBlocks.Make_buffered_set
(struct let name = ["test_set"] end)
(Block_hash.Set)
module SubBlocksMap =
SubBlocks.Make_buffered_map
(struct let name = ["test_map"] end)
(Make_value(struct
type t = int * string
let encoding = Data_encoding.(tup2 int31 string)
end))
(Block_hash.Map)
let test_subblock s =
SubBlocksSet.known s bh1 >>= fun known ->
Assert.is_false ~msg:__LOC__ known ;
SubBlocksSet.store s bh1 >>= fun () ->
SubBlocksSet.store s bh2 >>= fun () ->
SubBlocksSet.known s bh2 >>= fun known ->
Assert.is_true ~msg:__LOC__ known ;
SubBlocksSet.read_all s >>= fun set ->
let set' =
Block_hash.Set.empty
|> Block_hash.Set.add bh1
|> Block_hash.Set.add bh2 in
Assert.equal_block_set ~msg:__LOC__ set set' ;
SubBlocksSet.remove s bh2 >>= fun () ->
let set =
Block_hash.Set.empty
|> Block_hash.Set.add bh3'
|> Block_hash.Set.add bh3 in
SubBlocksSet.store_all s set >>= fun () ->
SubBlocksSet.elements s >>= fun elts ->
Assert.equal_block_hash_list ~msg:__LOC__
(List.sort Block_hash.compare elts)
(List.sort Block_hash.compare [bh3 ; bh3']) ;
SubBlocksSet.store s bh2 >>= fun () ->
SubBlocksSet.remove s bh3 >>= fun () ->
SubBlocksSet.elements s >>= fun elts ->
Assert.equal_block_hash_list ~msg:__LOC__
(List.sort Block_hash.compare elts)
(List.sort Block_hash.compare [bh2 ; bh3']) ;
SubBlocksMap.known s bh1 >>= fun known ->
Assert.is_false ~msg:__LOC__ known ;
let v1 = (3, "Non!")
and v2 = (12, "Beurk.") in
SubBlocksMap.store s bh1 v1 >>= fun () ->
SubBlocksMap.store s bh2 v2 >>= fun () ->
SubBlocksMap.known s bh1 >>= fun known ->
2017-04-05 20:24:26 +04:00
SubBlocksMap.read_opt s bh1 >>= fun v1' ->
Assert.equal ~msg:__LOC__ (Some v1) v1' ;
Assert.is_true ~msg:__LOC__ known ;
let map =
Block_hash.Map.empty
|> Block_hash.Map.add bh1 v1
|> Block_hash.Map.add bh2 v2 in
SubBlocksMap.read_all s >>= fun map' ->
Assert.equal_block_map ~eq:(=) ~msg:__LOC__ map map' ;
SubBlocksSet.remove_all s >>= fun () ->
SubBlocksSet.elements s >>= fun elts ->
Assert.equal_block_hash_list ~msg:__LOC__ elts [] ;
SubBlocksMap.read_all s >>= fun map' ->
Assert.equal_block_map ~eq:(=) ~msg:__LOC__ map map' ;
SubBlocksSet.store s bh3 >>= fun () ->
SubBlocks.indexes s >>= fun keys ->
Assert.equal_block_hash_list ~msg:__LOC__
(List.sort Block_hash.compare keys)
(List.sort Block_hash.compare [bh1;bh2;bh3]) ;
Lwt.return_unit
module SubSubBlocks =
Make_indexed_substore
(Make_substore(SubBlocks.Store)(struct let name = ["sub_blocks"] end))
(Block_hash)
2016-09-08 21:13:10 +04:00
(** *)
let tests_raw : (string * (Raw_store.t -> unit Lwt.t)) list = [
2016-09-08 21:13:10 +04:00
"init", test_init ;
"generic", test_generic (module Raw_store) ;
"generic_substore", test_generic (module Sub) ;
"generic_indexedstore",
(fun s -> test_generic (module SubBlocks.Store) (s, bh1)) ;
"generic_indexedsubstore",
(fun s -> test_generic (module SubSubBlocks.Store) ((s, bh1), bh2)) ;
"single", test_single (module Raw_store) ;
"single_substore", test_single (module Sub) ;
"single_indexedstore",
(fun s -> test_single (module SubBlocks.Store) (s, bh1)) ;
"single_indexedsubstore",
(fun s -> test_single (module SubSubBlocks.Store) ((s, bh1), bh2)) ;
"generic_list", test_generic_list (module Raw_store);
"generic_substore_list", test_generic_list (module Sub);
"generic_indexedstore_list",
(fun s -> test_generic_list (module SubBlocks.Store) (s, bh1));
"generic_indexedsubstore_list",
(fun s -> test_generic_list (module SubSubBlocks.Store) ((s, bh1), bh2)) ;
"hashset", test_hashset (module Raw_store) ;
"hashset_substore", test_hashset (module Sub) ;
"hashset_indexedstore",
(fun s -> test_hashset (module SubBlocks.Store) (s, bh1));
"hashset_indexedsubstore",
(fun s -> test_hashset (module SubSubBlocks.Store) ((s, bh1), bh2)) ;
"hashmap", test_hashmap (module Raw_store) ;
"hashmap_substore", test_hashmap (module Sub) ;
"hashmap_indexedstore",
(fun s -> test_hashmap (module SubBlocks.Store) (s, bh1));
"hashmap_indexedsubstore",
(fun s -> test_hashmap (module SubSubBlocks.Store) ((s, bh1), bh2)) ;
"subblock", test_subblock ;
]
let tests : (string * (Store.t -> unit Lwt.t)) list = [
"expand", test_expand ;
2016-09-08 21:13:10 +04:00
"block", test_block ;
]
2016-09-08 21:13:10 +04:00
let () =
Test.run "store."
(List.map (fun (s, f) -> s, wrap_raw_store_init f) tests_raw @
List.map (fun (s, f) -> s, wrap_store_init f) tests)