Skip to content

Commit 84b5bf5

Browse files
authored
Merge pull request #221 from mseri/rrd_ppx
CP-26583: Port Rrdd interface to PPX-based RPCs
2 parents b062924 + 8c0caa3 commit 84b5bf5

File tree

142 files changed

+596
-357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

142 files changed

+596
-357
lines changed

lib_test/gpumon_interface_test.ml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
2-
1+
open Idl_test_common
32

43
module GenPath = struct let test_data_path = "gpu_gen" end
54
module OldPath = struct let test_data_path = "test_data/gpumon" end
65

7-
module C = Gpumon_interface.RPC_API(Idl_test_common.GenTestData(GenPath))
8-
module T = Gpumon_interface.RPC_API(Idl_test_common.TestOldRpcs(OldPath))
6+
module C = Gpumon_interface.RPC_API(GenTestData(GenPath)(TJsonrpc))
7+
module T = Gpumon_interface.RPC_API(TestOldRpcs(OldPath)(TJsonrpc))
98

109
let tests =
1110
!C.implementation @ !T.implementation

lib_test/idl_test_common.ml

Lines changed: 92 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,39 @@ let read_str filename =
2727

2828
open Idl
2929

30-
module type PATHS = sig
30+
module type CONFIG = sig
3131
val test_data_path : string
3232
(** Path under which we look for or generate requests and responses. For example,
3333
if test_data_path = 'foo', this module will search for or generate requests
3434
matching 'foo/requests/<RPC name>.request.<n>' and responses matching
3535
'foo/responses/<RPC name>.response.<n>' *)
3636
end
3737

38+
module type MARSHALLER = sig
39+
val string_of_call : Rpc.call -> string
40+
val call_of_string : string -> Rpc.call
41+
val string_of_response : Rpc.response -> string
42+
val response_of_string : string -> Rpc.response
43+
val to_string : Rpc.t -> string
44+
val of_string : string -> Rpc.t
45+
end
46+
47+
(* Slightly annoyingly, both RPC modules have a slightly different signature. Fix it here *)
48+
module TJsonrpc : MARSHALLER = struct
49+
include Jsonrpc
50+
let string_of_call call = string_of_call call
51+
let string_of_response response = string_of_response response
52+
end
53+
54+
module TXmlrpc : MARSHALLER = struct
55+
include Xmlrpc
56+
let call_of_string s = call_of_string s
57+
let response_of_string s = response_of_string s
58+
let of_string s = of_string s
59+
end
60+
61+
62+
3863
(** The following module implements test cases that write test
3964
RPC requests and responses in JSON that can be used to
4065
verify that subsequent versions of an API can still parse
@@ -45,8 +70,8 @@ end
4570
this module.
4671
4772
The test data will be written to the path specified in the
48-
PATH module passed in *)
49-
module GenTestData (P:PATHS) = struct
73+
CONFIG module passed in *)
74+
module GenTestData (C:CONFIG) (M:MARSHALLER) = struct
5075
type implementation = unit Alcotest.test_case list ref
5176

5277
let tests : unit Alcotest.test_case list ref = ref []
@@ -63,14 +88,36 @@ module GenTestData (P:PATHS) = struct
6388
let returning a err = Returning (a, err)
6489
let (@->) = fun t f -> Function (t, f)
6590

91+
open M
92+
6693
let declare name _ ty =
6794
let rec inner : type b. (((string * Rpc.t) list * Rpc.t list) list) -> b fn -> unit = fun params ->
6895
function
6996
| Function (t, f) -> begin
7097
let vs = Rpc_genfake.genall 2 (match t.Param.name with Some n -> n | None -> t.Param.typedef.Rpc.Types.name) t.Param.typedef.Rpc.Types.ty in
7198
let marshalled = List.map (fun v -> Rpcmarshal.marshal t.Param.typedef.Rpc.Types.ty v) vs in
7299
match t.Param.name with
73-
| Some n -> inner (List.flatten (List.map (fun marshalled -> List.map (fun (named,unnamed) -> (((n,marshalled)::named),unnamed)) params) marshalled)) f
100+
| Some n ->
101+
inner
102+
(List.flatten
103+
(List.map
104+
(fun marshalled ->
105+
match marshalled, t.Param.typedef.Rpc.Types.ty with
106+
| Rpc.Enum [], Rpc.Types.Option _ ->
107+
params
108+
| Rpc.Enum [x], Rpc.Types.Option _ ->
109+
List.map
110+
(fun (named,unnamed) ->
111+
(((n, x)::named),unnamed))
112+
params
113+
| _, _ ->
114+
List.map
115+
(fun (named,unnamed) ->
116+
(((n,marshalled)::named),unnamed))
117+
params
118+
) marshalled
119+
)
120+
) f
74121
| None -> inner (List.flatten (List.map (fun marshalled -> List.map (fun (named,unnamed) -> (named,(marshalled::unnamed))) params) marshalled)) f
75122
end
76123
| Returning (t, e) ->
@@ -85,40 +132,44 @@ module GenTestData (P:PATHS) = struct
85132
let call = Rpc.call wire_name args in
86133
call) params in
87134
List.iteri (fun i call ->
88-
let request_str = Jsonrpc.string_of_call call in
135+
let request_str = string_of_call call in
89136
write_str
90-
(Printf.sprintf "%s/requests/%s.request.%d" P.test_data_path wire_name i)
137+
(Printf.sprintf "%s/requests/%s.request.%d" C.test_data_path wire_name i)
91138
request_str) calls;
92139
let vs = Rpc_genfake.genall 2 (match t.Param.name with Some n -> n | None -> t.Param.typedef.Rpc.Types.name) t.Param.typedef.Rpc.Types.ty in
93140
let marshalled_vs = List.map (fun v -> Rpc.success (Rpcmarshal.marshal t.Param.typedef.Rpc.Types.ty v)) vs in
94141
let errs = Rpc_genfake.genall 2 "error" e.Error.def.Rpc.Types.ty in
95142
let marshalled_errs = List.map (fun err -> Rpc.failure (Rpcmarshal.marshal e.Error.def.Rpc.Types.ty err)) errs in
96143
List.iteri (fun i response ->
97-
let response_str = Jsonrpc.string_of_response response in
144+
let response_str = string_of_response response in
98145
write_str
99-
(Printf.sprintf "%s/responses/%s.response.%d" P.test_data_path wire_name i)
146+
(Printf.sprintf "%s/responses/%s.response.%d" C.test_data_path wire_name i)
100147
response_str) (marshalled_vs @ marshalled_errs)
101148
in
102149
let test_fn () =
103150
let mkdir_safe p = begin try Unix.mkdir p 0o755 with Unix.Unix_error (EEXIST, _, _) -> () end in
104-
mkdir_safe P.test_data_path;
105-
mkdir_safe (Printf.sprintf "%s/requests" P.test_data_path);
106-
mkdir_safe (Printf.sprintf "%s/responses" P.test_data_path);
151+
mkdir_safe C.test_data_path;
152+
mkdir_safe (Printf.sprintf "%s/requests" C.test_data_path);
153+
mkdir_safe (Printf.sprintf "%s/responses" C.test_data_path);
107154
inner [[],[]] ty in
108155
tests := (Printf.sprintf "Generate test data for '%s'" (Idl.get_wire_name !description name), `Quick, test_fn) :: !tests
109156
end
110157

111-
let get_arg call has_named name =
158+
let get_arg call has_named name is_opt =
112159
match has_named, name, call.Rpc.params with
113160
| true, Some n, (Rpc.Dict named)::unnamed -> begin
114-
match List.partition (fun (x,_) -> x = n) named with
115-
| (_,arg)::dups,others -> Result.Ok (arg, {call with Rpc.params = (Rpc.Dict (dups @ others))::unnamed })
116-
| _,_ -> Result.Error (`Msg (Printf.sprintf "Expecting named argument '%s'" n))
161+
match List.partition (fun (x,_) -> x = n) named with
162+
| (_,arg)::dups,others when is_opt ->
163+
Result.Ok (Rpc.Enum [arg], {call with Rpc.params = (Rpc.Dict (dups @ others))::unnamed })
164+
| [], _others when is_opt -> Result.Ok (Rpc.Enum [], call)
165+
| (_,arg)::dups,others ->
166+
Result.Ok (arg, {call with Rpc.params = (Rpc.Dict (dups @ others))::unnamed })
167+
| _,_ -> Result.Error (`Msg (Printf.sprintf "Expecting named argument '%s'" n))
117168
end
118169
| true, None, (Rpc.Dict named)::unnamed -> begin
119-
match unnamed with
120-
| head::tail -> Result.Ok (head, {call with Rpc.params = (Rpc.Dict named)::tail})
121-
| _ -> Result.Error (`Msg "Incorrect number of arguments")
170+
match unnamed with
171+
| head::tail -> Result.Ok (head, {call with Rpc.params = (Rpc.Dict named)::tail})
172+
| _ -> Result.Error (`Msg "Incorrect number of arguments")
122173
end
123174
| true, _, _ -> begin
124175
Result.Error (`Msg "Marshalling error: Expecting dict as first argument when named parameters exist")
@@ -127,9 +178,9 @@ let get_arg call has_named name =
127178
Result.Ok (head, {call with Rpc.params = tail})
128179
end
129180
| false, None, [] ->
130-
Result.Error (`Msg "Incorrect number of arguments")
181+
Result.Error (`Msg "Incorrect number of arguments")
131182
| false, Some _, _ ->
132-
failwith "Can't happen by construction"
183+
failwith "Can't happen by construction"
133184

134185
exception NoDescription
135186
exception MarshalError of string
@@ -138,7 +189,7 @@ exception MarshalError of string
138189
(** The following module will generate alcotest test cases to verify
139190
that a set of requests and responses can be successfully parsed.
140191
141-
The PATHS module specifies the location for the test data as
192+
The CONFIG module specifies the location for the test data as
142193
`test_data_path`. Requests and responses will be looked up in
143194
this location in the subdirectories `requests` and `responses`.
144195
The actual data must be in files following the naming convention
@@ -148,7 +199,7 @@ exception MarshalError of string
148199
ensure it accurately represents how the server would parse the
149200
json.
150201
*)
151-
module TestOldRpcs (P : PATHS) = struct
202+
module TestOldRpcs (C : CONFIG) (M : MARSHALLER) = struct
152203
open Rpc
153204
type implementation = unit Alcotest.test_case list ref
154205

@@ -167,6 +218,8 @@ module TestOldRpcs (P : PATHS) = struct
167218
let returning a b = Returning (a,b)
168219
let (@->) = fun t f -> Function (t, f)
169220

221+
open M
222+
170223
let rec has_named_args : type a. a fn -> bool =
171224
function
172225
| Function (t, f) -> begin
@@ -191,22 +244,31 @@ module TestOldRpcs (P : PATHS) = struct
191244
let rec read_all path extension i =
192245
try
193246
let call =
194-
read_str (Printf.sprintf "%s/%s/%s.%s.%d" P.test_data_path path wire_name extension i) in
247+
read_str (Printf.sprintf "%s/%s/%s.%s.%d" C.test_data_path path wire_name extension i) in
195248
call :: read_all path extension (i+1)
196249
with _ -> []
197250
in
198251

199-
let calls = read_all "requests" "request" 0 |> List.map Jsonrpc.call_of_string in
200-
let responses = read_all "responses" "response" 0 |> List.map Jsonrpc.response_of_string in
252+
let calls = read_all "requests" "request" 0 |> List.map call_of_string in
253+
let responses = read_all "responses" "response" 0 |> List.map response_of_string in
201254

202255
let verify : type a. a Rpc.Types.typ -> Rpc.t -> a = fun typ rpc ->
256+
let rec sort_dicts ty =
257+
let open Rpc in
258+
match ty with
259+
| Dict kvs' ->
260+
let kvs = List.map (fun (k,v) -> (k, sort_dicts v)) kvs' in
261+
Dict (List.sort (fun (k1,_) (k2,_) -> String.compare k1 k2) kvs)
262+
| Enum ts -> Enum (List.map sort_dicts ts)
263+
| _ -> ty
264+
in
203265
match Rpcmarshal.unmarshal typ rpc with
204266
| Ok x ->
205267
let check = Rpcmarshal.marshal typ x in
206-
if check <> rpc then begin
268+
if (to_string (sort_dicts check)) <> (to_string (sort_dicts rpc)) then begin
207269
let err = Printf.sprintf "Round-trip failed. Before: '%s' After: '%s'"
208-
(Jsonrpc.to_string rpc)
209-
(Jsonrpc.to_string check) in
270+
(to_string rpc)
271+
(to_string check) in
210272
raise (MarshalError err)
211273
end;
212274
x
@@ -220,7 +282,8 @@ module TestOldRpcs (P : PATHS) = struct
220282
match f with
221283
| Function (t, f) -> begin
222284
let (arg_rpc, call') =
223-
match get_arg call has_named t.Param.name with
285+
let is_opt = match t.Param.typedef.Rpc.Types.ty with Rpc.Types.Option _ -> true | _ -> false in
286+
match get_arg call has_named t.Param.name is_opt with
224287
| Result.Ok (x,y) -> (x,y)
225288
| Result.Error (`Msg m) -> raise (MarshalError m)
226289
in

lib_test/memory_interface_test.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11

2-
2+
open Idl_test_common
33

44
module GenPath = struct let test_data_path = "mem_gen" end
55
module OldPath = struct let test_data_path = "test_data/memory" end
66

7-
module C = Memory_interface.API(Idl_test_common.GenTestData(GenPath))
8-
module T = Memory_interface.API(Idl_test_common.TestOldRpcs(OldPath))
7+
module C = Memory_interface.API(GenTestData(GenPath)(TJsonrpc))
8+
module T = Memory_interface.API(TestOldRpcs(OldPath)(TJsonrpc))
99

1010
let tests =
1111
!C.implementation @ !T.implementation

lib_test/network_interface_test.ml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11

22

3+
open Idl_test_common
34

45
module GenPath = struct let test_data_path = "net_gen" end
56
module OldPath = struct let test_data_path = "test_data/network" end
67

7-
module C = Network_interface.Interface_API(Idl_test_common.GenTestData(GenPath))
8-
module T = Network_interface.Interface_API(Idl_test_common.TestOldRpcs(OldPath))
8+
module C = Network_interface.Interface_API(GenTestData(GenPath)(TJsonrpc))
9+
module T = Network_interface.Interface_API(TestOldRpcs(OldPath)(TJsonrpc))
910

1011
let tests =
1112
!C.implementation @ !T.implementation

0 commit comments

Comments
 (0)