2 * Copyright (c) 2015, Facebook, Inc.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
11 (* These are basically the same tests as in
12 * test/integration_ml/saved_state/test_naming_table_sqlite_fallback.ml, but
13 * as stripped down to just the basics as possible to make finding the root
14 * cause of test failures easier. *)
18 module Types_pos_asserter
= Asserter.Make_asserter
(struct
19 type t
= FileInfo.pos
* Naming_types.kind_of_type
21 let to_string (pos
, type_of_type
) =
24 (FileInfo.show_pos pos
)
25 (Naming_types.kind_of_type_to_enum type_of_type
)
30 module Pos_asserter
= Asserter.Make_asserter
(struct
33 let to_string pos
= Printf.sprintf
"(%s)" (FileInfo.show_pos pos
)
44 function bar
(): void
{}
54 let write_and_parse_test_files () =
56 List.map
files ~f
:(fun (fn
, contents
) ->
57 (Relative_path.from_root ~suffix
:fn
, contents
))
59 List.iter
files ~f
:(fun (fn
, contents
) ->
60 let fn = Path.make
(Relative_path.to_absolute
fn) in
61 let dir = Path.dirname
fn in
62 Disk.mkdir_p
(Path.to_string dir);
63 Disk.write_file ~file
:(Path.to_string fn) ~contents
);
64 let (file_infos
, errors
, failed_parsing
) =
67 Relative_path.Set.empty
68 ~get_next
:(MultiWorker.next None
(List.map
files ~f
:fst
))
72 if not
(Errors.is_empty errors
) then (
73 Errors.iter_error_list
75 List.iter
(Errors.to_list e
) ~f
:(fun (pos
, msg
) ->
76 eprintf
"%s: %s\n" (Pos.string (Pos.to_absolute pos
)) msg
))
78 failwith
"Expected no errors from parsing."
80 if failed_parsing
<> Relative_path.Set.empty
then
81 failwith
"Expected all files to pass parsing.";
82 Naming_table.create file_infos
84 let run_naming_table_test f
=
85 Tempfile.with_real_tempdir
(fun path
->
86 Relative_path.set_path_prefix
88 (Path.concat path
"root/");
93 heap_size
= 1024 * 1024;
102 let (_
: SharedMem.handle
) = SharedMem.init
config ~num_workers
:0 in
103 let unbacked_naming_table = write_and_parse_test_files () in
104 let db_name = Path.to_string (Path.concat path
"naming_table.sqlite") in
105 let save_results = Naming_table.save
unbacked_naming_table db_name in
106 Asserter.Int_asserter.assert_equals
108 Naming_sqlite.(save_results.files_added
+ save_results.symbols_added
)
109 "Expected to add eight rows (four files and four symbols)";
111 let popt = ParserOptions.default
in
112 let tcopt = TypecheckerOptions.default
in
113 let ctx_for_sqlite_load = Provider_context.empty_for_test ~
popt ~
tcopt in
114 let backed_naming_table =
115 Naming_table.load_from_sqlite
ctx_for_sqlite_load db_name
118 Provider_backend.set_local_memory_backend_with_defaults
();
120 Provider_context.empty_for_tool
123 ~backend
:(Provider_backend.get
())
125 (try f ~
ctx ~
unbacked_naming_table ~
backed_naming_table ~
db_name
128 "NOTE: backend was local-memory for this exception's test run\n";
130 Provider_backend.set_shared_memory_backend
();
132 Provider_context.empty_for_tool
135 ~backend
:(Provider_backend.get
())
137 (try f ~
ctx ~
unbacked_naming_table ~
backed_naming_table ~
db_name
140 "NOTE: backend was shared-memory for this exception's test run\n";
144 let test_get_pos () =
145 run_naming_table_test
146 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table:_ ~
db_name:_
->
147 Types_pos_asserter.assert_option_equals
150 (FileInfo.Class
, Relative_path.from_root ~suffix
:"foo.php"),
151 Naming_types.TClass
))
152 (Naming_provider.get_type_pos_and_kind
ctx "\\Foo")
153 "Check for class type";
154 Pos_asserter.assert_option_equals
157 (FileInfo.Fun
, Relative_path.from_root ~suffix
:"bar.php")))
158 (Naming_provider.get_fun_pos
ctx "\\bar")
159 "Check for function";
160 Types_pos_asserter.assert_option_equals
163 (FileInfo.Typedef
, Relative_path.from_root ~suffix
:"baz.php"),
164 Naming_types.TTypedef
))
165 (Naming_provider.get_type_pos_and_kind
ctx "\\Baz")
166 "Check for typedef type";
167 Pos_asserter.assert_option_equals
170 (FileInfo.Const
, Relative_path.from_root ~suffix
:"qux.php")))
171 (Naming_provider.get_const_pos
ctx "\\Qux")
174 let test_get_canon_name () =
175 run_naming_table_test
176 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table:_ ~
db_name:_
->
177 (* Since we're parsing but not naming, the canon heap must fall back to the
178 files on disk, which is the situation we'd be in when loading from a
180 Asserter.String_asserter.assert_option_equals
182 (Naming_provider.get_type_canon_name
ctx "\\foo")
183 "Check for class canon name";
184 Asserter.String_asserter.assert_option_equals
186 (Naming_provider.get_fun_canon_name
ctx "\\bar")
187 "Check for function canon name lowercase";
188 Asserter.String_asserter.assert_option_equals
190 (Naming_provider.get_fun_canon_name
ctx "\\BAR")
191 "Check for function canon name uppercase";
192 Asserter.String_asserter.assert_option_equals
194 (Naming_provider.get_type_canon_name
ctx "\\baz")
195 "Check for typedef canon name")
198 run_naming_table_test
199 (fun ~
ctx:_ ~
unbacked_naming_table ~
backed_naming_table ~
db_name:_
->
200 let foo_path = Relative_path.from_root ~suffix
:"foo.php" in
202 Naming_table.get_file_info
unbacked_naming_table foo_path
204 let unbacked_naming_table =
205 Naming_table.remove
unbacked_naming_table foo_path
208 Naming_table.get_file_info
unbacked_naming_table foo_path
212 Naming_table.get_file_info
backed_naming_table foo_path
214 let backed_naming_table =
215 Naming_table.remove
backed_naming_table foo_path
218 Naming_table.get_file_info
backed_naming_table foo_path
221 let test_get_sqlite_paths () =
222 run_naming_table_test
223 (fun ~
ctx:_ ~
unbacked_naming_table:_ ~
backed_naming_table ~
db_name ->
224 Asserter.String_asserter.assert_option_equals
226 (Naming_table.get_reverse_naming_fallback_path
())
227 "get_reverse_naming_fallback_path should return the expected value";
229 Asserter.String_asserter.assert_option_equals
231 (Naming_table.get_forward_naming_fallback_path
backed_naming_table)
232 "get_forward_naming_fallback_path should return the expected value")
234 let test_local_changes () =
235 run_naming_table_test
236 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table ~
db_name ->
237 let a_name = "CONST_IN_A" in
239 let a_file = Relative_path.from_root ~suffix
:"a.php" in
240 let a_pos = FileInfo.File
(FileInfo.Const
, a_file) in
242 FileInfo.{ FileInfo.empty_t
with consts
= [(a_pos, a_name)] }
244 let backed_naming_table =
245 Naming_table.update
backed_naming_table a_file a_file_info
247 let changes_since_baseline_path = "/tmp/base_plus_changes" in
248 Naming_table.save_changes_since_baseline
250 changes_since_baseline_path;
251 let (changes_since_baseline
: Naming_table.changes_since_baseline
) =
252 Marshal.from_string
(Disk.cat
changes_since_baseline_path) 0
254 Asserter.Relative_path_asserter.assert_list_equals
256 (Naming_table.get_files_changed_since_baseline changes_since_baseline
)
257 "Expected files changed since baseline to be correct";
258 let backed_naming_table'
=
259 Naming_table.load_from_sqlite_with_changes_since_baseline
261 changes_since_baseline
266 (Naming_table.get_file_info
backed_naming_table'
a_file)
268 Asserter.Bool_asserter.assert_equals
270 (a_file_info = a_file_info'
)
271 "Expected file info to be found in the naming table";
274 Option.value_exn
(Naming_provider.get_const_pos
ctx a_name)
276 Asserter.Bool_asserter.assert_equals
279 "Expected position of constant to be found in the naming table")
281 let test_context_changes_consts () =
282 run_naming_table_test
283 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table:_ ~
db_name:_
->
285 Provider_context.add_or_overwrite_entry_contents
287 ~path
:(Relative_path.from_root ~suffix
:"foo.php")
293 Provider_context.add_or_overwrite_entry_contents
295 ~path
:(Relative_path.from_root ~suffix
:"qux.php")
297 const
int New_qux
= 5;
300 Asserter.Relative_path_asserter.assert_option_equals
301 (Some
(Relative_path.from_root ~suffix
:"qux.php"))
302 (Naming_provider.get_const_path
ctx "\\New_qux")
303 "New const in context should be visible";
304 Asserter.Relative_path_asserter.assert_option_equals
306 (Naming_provider.get_const_path
ctx "\\Qux")
307 "Old, deleted const in context should NOT be visible")
309 let test_context_changes_funs () =
310 run_naming_table_test
311 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table:_ ~
db_name:_
->
313 Provider_context.add_or_overwrite_entry_contents
315 ~path
:(Relative_path.from_root ~suffix
:"foo.php")
321 Provider_context.add_or_overwrite_entry_contents
323 ~path
:(Relative_path.from_root ~suffix
:"bar.php")
325 function new_bar
(): void
{}
328 Asserter.Relative_path_asserter.assert_option_equals
329 (Some
(Relative_path.from_root ~suffix
:"bar.php"))
330 (Naming_provider.get_fun_path
ctx "\\new_bar")
331 "New function in context should be visible";
332 Asserter.Relative_path_asserter.assert_option_equals
334 (Naming_provider.get_fun_path
ctx "\\bar")
335 "Old, deleted function in context should NOT be visible";
337 Asserter.String_asserter.assert_option_equals
339 (Naming_provider.get_fun_canon_name
ctx "\\NeW_bAr")
340 "New function in context should be accessible by canon name";
342 (* NB: under shared-memory provider, this doesn't hold true if we made
343 a call to `get_fun_canon_name` before we added the context entry, as
344 the result will be cached. The caller is expected to have manually
345 removed any old reverse naming table entries manually in that case. *)
346 Asserter.String_asserter.assert_option_equals
348 (Naming_provider.get_fun_canon_name
ctx "\\BAR")
349 "Old function in context should NOT be accessible by canon name")
351 let test_context_changes_classes () =
352 run_naming_table_test
353 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table:_ ~
db_name:_
->
355 Provider_context.add_or_overwrite_entry_contents
357 ~path
:(Relative_path.from_root ~suffix
:"foo.php")
362 Asserter.Relative_path_asserter.assert_option_equals
363 (Some
(Relative_path.from_root ~suffix
:"foo.php"))
364 (Naming_provider.get_class_path
ctx "\\NewFoo")
365 "New class in context should be visible";
366 Asserter.Relative_path_asserter.assert_option_equals
368 (Naming_provider.get_class_path
ctx "\\Foo")
369 "Old class in context should NOT be visible";
371 Asserter.String_asserter.assert_option_equals
373 (Naming_provider.get_type_canon_name
ctx "\\NEWFOO")
374 "New class in context should be accessible by canon name";
376 (* NB: under shared-memory provider, this doesn't hold true if we made
377 a call to `get_type_canon_name` before we added the context entry, as
378 the result will be cached. The caller is expected to have manually
379 removed any old reverse naming table entries manually in that case. *)
380 Asserter.String_asserter.assert_option_equals
382 (Naming_provider.get_type_canon_name
ctx "\\FOO")
383 "Old class in context should NOT be accessible by canon name")
385 let test_context_changes_typedefs () =
386 run_naming_table_test
387 (fun ~
ctx ~
unbacked_naming_table:_ ~
backed_naming_table:_ ~
db_name:_
->
389 Provider_context.add_or_overwrite_entry_contents
391 ~path
:(Relative_path.from_root ~suffix
:"baz.php")
396 Asserter.Relative_path_asserter.assert_option_equals
397 (Some
(Relative_path.from_root ~suffix
:"baz.php"))
398 (Naming_provider.get_typedef_path
ctx "\\NewBaz")
399 "New typedef in context should be visible";
400 Asserter.Relative_path_asserter.assert_option_equals
402 (Naming_provider.get_typedef_path
ctx "\\Baz")
403 "Old typedef in context should NOT be visible";
405 Asserter.String_asserter.assert_option_equals
407 (Naming_provider.get_type_canon_name
ctx "\\NEWBAZ")
408 "New typedef in context should be accessible by canon name";
410 (* NB: under shared-memory provider, this doesn't hold true if we made
411 a call to `get_type_canon_name` before we added the context entry, as
412 the result will be cached. The caller is expected to have manually
413 removed any old reverse naming table entries manually in that case. *)
414 Asserter.String_asserter.assert_option_equals
416 (Naming_provider.get_type_canon_name
ctx "\\BAZ")
417 "Old typedef in context should NOT be accessible by canon name")
424 heap_size
= 1024 * 1024;
433 let (_
: SharedMem.handle
) = SharedMem.init
config ~num_workers
:0 in
436 ("test_get_pos", test_get_pos);
437 ("test_get_canon_name", test_get_canon_name);
438 ("test_remove", test_remove);
439 ("test_get_sqlite_paths", test_get_sqlite_paths);
440 ("test_local_changes", test_local_changes);
441 ("test_context_changes_consts", test_context_changes_consts);
442 ("test_context_changes_funs", test_context_changes_funs);
443 ("test_context_changes_classes", test_context_changes_classes);
444 ("test_context_changes_typedefs", test_context_changes_typedefs);