Updating submodules
[hiphop-php.git] / hphp / hack / test / unit / naming / naming_table_tests.ml
blob5ce0cac543a34b8e33b6f52ade45a6f79f4fdb0b
1 (*
2 * Copyright (c) 2015, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the MIT license found in the
6 * LICENSE file in the "hack" directory of this source tree.
9 *)
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. *)
16 open Hh_prelude
18 let deps_mode = Typing_deps_mode.InMemoryMode None
20 module Types_pos_asserter = Asserter.Make_asserter (struct
21 type t = FileInfo.pos * Naming_types.kind_of_type
23 let to_string (pos, kind_of_type) =
24 Printf.sprintf
25 "(%s, %s)"
26 (FileInfo.show_pos pos)
27 (Naming_types.show_kind_of_type kind_of_type)
29 let is_equal = Poly.( = )
30 end)
32 module Pos_asserter = Asserter.Make_asserter (struct
33 type t = FileInfo.pos
35 let to_string pos = Printf.sprintf "(%s)" (FileInfo.show_pos pos)
37 let is_equal = FileInfo.equal_pos
38 end)
40 let files =
42 ("foo.php", {|<?hh
43 class Foo {}
44 |});
45 ("bar.php", {|<?hh
46 function bar(): void {}
47 |});
48 ("baz.php", {|<?hh
49 type Baz = Foo;
50 |});
51 ("qux.php", {|<?hh
52 const int Qux = 5;
53 |});
54 ("qux.php", {|<?hh
55 const int Qux = 5;
56 |});
57 ("corge.php", {|<?hh
58 new module Corge {}
59 |});
60 ( "corge2.php",
61 {|<?hh
62 // modules are case sensitive, this is a different symbol
63 new module corge {}
68 let write_and_parse_test_files ctx =
69 let files =
70 List.map files ~f:(fun (fn, contents) ->
71 (Relative_path.from_root ~suffix:fn, contents))
73 List.iter files ~f:(fun (fn, contents) ->
74 let fn = Path.make (Relative_path.to_absolute fn) in
75 let dir = Path.dirname fn in
76 Disk.mkdir_p (Path.to_string dir);
77 Disk.write_file ~file:(Path.to_string fn) ~contents);
78 let get_next = MultiWorker.next None (List.map files ~f:fst) in
79 let file_infos =
80 Direct_decl_service.go ctx None ~get_next ~trace:true ~cache_decls:false
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
87 Relative_path.Root
88 (Path.concat path "root/");
89 let config =
90 SharedMem.
92 global_size = 1024;
93 heap_size = 1024 * 1024;
94 hash_table_pow = 10;
95 shm_dirs = [];
96 shm_use_sharded_hashtbl = false;
97 shm_cache_size = -1;
98 shm_min_avail = 0;
99 log_level = 0;
100 sample_rate = 0.0;
101 compression = 0;
104 let popt =
105 ParserOptions.{ default with allow_unstable_features = true }
107 let tcopt = TypecheckerOptions.default in
108 let ctx =
109 Provider_context.empty_for_tool
110 ~popt
111 ~tcopt
112 ~backend:(Provider_backend.get ())
113 ~deps_mode
115 let (_ : SharedMem.handle) = SharedMem.init config ~num_workers:0 in
116 let unbacked_naming_table = write_and_parse_test_files ctx in
117 let db_name = Path.to_string (Path.concat path "naming_table.sqlite") in
118 let save_results = Naming_table.save unbacked_naming_table db_name in
119 Asserter.Int_asserter.assert_equals
121 Naming_sqlite.(save_results.files_added + save_results.symbols_added)
122 "Expected to add 12 rows (6 files and 6 symbols)";
124 let ctx_for_sqlite_load =
125 Provider_context.empty_for_test ~popt ~tcopt ~deps_mode
127 let backed_naming_table =
128 Naming_table.load_from_sqlite ctx_for_sqlite_load db_name
131 Provider_backend.set_local_memory_backend_with_defaults_for_test ();
132 let ctx =
133 Provider_context.empty_for_tool
134 ~popt
135 ~tcopt
136 ~backend:(Provider_backend.get ())
137 ~deps_mode
139 (* load_from_sqlite will call set_naming_db_path for the ctx it's given, but
140 here is a fresh ctx with a fresh backend so we have to set it again. *)
141 Db_path_provider.set_naming_db_path
142 (Provider_context.get_backend ctx)
143 (Some (Naming_sqlite.Db_path db_name));
144 (try
146 ~ctx
147 ~unbacked_naming_table
148 ~backed_naming_table
149 ~db_name
150 ~tmp_path:path
151 with
152 | e ->
153 Printf.eprintf
154 "NOTE: backend was local-memory for this exception's test run\n";
155 raise e);
156 Provider_backend.set_shared_memory_backend ();
157 let ctx =
158 Provider_context.empty_for_tool
159 ~popt
160 ~tcopt
161 ~backend:(Provider_backend.get ())
162 ~deps_mode
164 (try
166 ~ctx
167 ~unbacked_naming_table
168 ~backed_naming_table
169 ~db_name
170 ~tmp_path:path
171 with
172 | e ->
173 Printf.eprintf
174 "NOTE: backend was shared-memory for this exception's test run\n";
175 raise e);
176 true)
178 let test_get_pos () =
179 run_naming_table_test
180 (fun
181 ~ctx
182 ~unbacked_naming_table:_
183 ~backed_naming_table:_
184 ~db_name:_
185 ~tmp_path:_
187 Types_pos_asserter.assert_option_equals
188 (Some
189 ( FileInfo.File
190 (FileInfo.Class, Relative_path.from_root ~suffix:"foo.php"),
191 Naming_types.TClass ))
192 (Naming_provider.get_type_pos_and_kind ctx "\\Foo")
193 "Check for class type";
194 Pos_asserter.assert_option_equals
195 (Some
196 (FileInfo.File
197 (FileInfo.Fun, Relative_path.from_root ~suffix:"bar.php")))
198 (Naming_provider.get_fun_pos ctx "\\bar")
199 "Check for function";
200 Types_pos_asserter.assert_option_equals
201 (Some
202 ( FileInfo.File
203 (FileInfo.Typedef, Relative_path.from_root ~suffix:"baz.php"),
204 Naming_types.TTypedef ))
205 (Naming_provider.get_type_pos_and_kind ctx "\\Baz")
206 "Check for typedef type";
207 Pos_asserter.assert_option_equals
208 (Some
209 (FileInfo.File
210 (FileInfo.Const, Relative_path.from_root ~suffix:"qux.php")))
211 (Naming_provider.get_const_pos ctx "\\Qux")
212 "Check for const";
213 Pos_asserter.assert_option_equals
214 (Some
215 (FileInfo.File
216 (FileInfo.Module, Relative_path.from_root ~suffix:"corge.php")))
217 (Naming_provider.get_module_pos ctx "Corge")
218 "Check for module")
220 let test_get_canon_name () =
221 run_naming_table_test
222 (fun
223 ~ctx
224 ~unbacked_naming_table:_
225 ~backed_naming_table:_
226 ~db_name:_
227 ~tmp_path:_
229 (* Since we're parsing but not naming, the canon heap must fall back to the
230 files on disk, which is the situation we'd be in when loading from a
231 saved state. *)
232 Asserter.String_asserter.assert_option_equals
233 (Some "\\Foo")
234 (Naming_provider.get_type_canon_name ctx "\\foo")
235 "Check for class canon name";
236 Asserter.String_asserter.assert_option_equals
237 (Some "\\bar")
238 (Naming_provider.get_fun_canon_name ctx "\\bar")
239 "Check for function canon name lowercase";
240 Asserter.String_asserter.assert_option_equals
241 (Some "\\bar")
242 (Naming_provider.get_fun_canon_name ctx "\\BAR")
243 "Check for function canon name uppercase";
244 Asserter.String_asserter.assert_option_equals
245 (Some "\\Baz")
246 (Naming_provider.get_type_canon_name ctx "\\baz")
247 "Check for typedef canon name")
249 let test_remove () =
250 run_naming_table_test
251 (fun
252 ~ctx:_
253 ~unbacked_naming_table
254 ~backed_naming_table
255 ~db_name:_
256 ~tmp_path:_
258 let foo_path = Relative_path.from_root ~suffix:"foo.php" in
259 assert (
260 Naming_table.get_file_info unbacked_naming_table foo_path
261 |> Option.is_some);
262 let unbacked_naming_table =
263 Naming_table.remove unbacked_naming_table foo_path
265 assert (
266 Naming_table.get_file_info unbacked_naming_table foo_path
267 |> Option.is_none);
269 assert (
270 Naming_table.get_file_info backed_naming_table foo_path
271 |> Option.is_some);
272 let backed_naming_table =
273 Naming_table.remove backed_naming_table foo_path
275 assert (
276 Naming_table.get_file_info backed_naming_table foo_path
277 |> Option.is_none))
279 let test_get_sqlite_paths () =
280 run_naming_table_test
281 (fun ~ctx ~unbacked_naming_table:_ ~backed_naming_table ~db_name ~tmp_path:_
283 let provider_path =
284 match
285 Db_path_provider.get_naming_db_path (Provider_context.get_backend ctx)
286 with
287 | None -> None
288 | Some (Naming_sqlite.Db_path path) -> Some path
290 Asserter.String_asserter.assert_option_equals
291 (Some db_name)
292 provider_path
293 "get_naming_db_path should return the expected value";
295 Asserter.String_asserter.assert_option_equals
296 (Some db_name)
297 (Naming_table.get_forward_naming_fallback_path backed_naming_table)
298 "get_forward_naming_fallback_path should return the expected value")
300 let test_local_changes () =
301 run_naming_table_test
302 (fun ~ctx ~unbacked_naming_table:_ ~backed_naming_table ~db_name ~tmp_path
304 let a_name = "CONST_IN_A" in
306 let a_file = Relative_path.from_root ~suffix:"a.php" in
307 let a_pos = FileInfo.File (FileInfo.Const, a_file) in
308 let decl_hash = None in
309 let a_file_info =
310 FileInfo.
312 FileInfo.empty_t with
313 ids =
315 FileInfo.empty_ids with
316 FileInfo.consts =
318 FileInfo.
320 pos = a_pos;
321 name = a_name;
322 decl_hash;
323 sort_text = None;
327 position_free_decl_hash = Some (Int64.of_int 1234567);
330 let backed_naming_table =
331 Naming_table.update backed_naming_table a_file a_file_info
333 let changes_since_baseline_path =
334 Path.concat tmp_path "base_plus_changes" |> Path.to_string
336 Naming_table.save_changes_since_baseline
337 backed_naming_table
338 ~destination_path:changes_since_baseline_path;
339 let (changes_since_baseline : Naming_table.changes_since_baseline) =
340 Marshal.from_string (Disk.cat changes_since_baseline_path) 0
342 Asserter.Relative_path_asserter.assert_list_equals
343 [a_file]
344 (Naming_table.get_files_changed_since_baseline changes_since_baseline)
345 "Expected files changed since baseline to be correct";
346 let backed_naming_table' =
347 Naming_table.load_from_sqlite_with_changes_since_baseline
349 changes_since_baseline
350 db_name
352 let a_file_info' =
353 Option.value_exn
354 (Naming_table.get_file_info backed_naming_table' a_file)
356 Asserter.Bool_asserter.assert_equals
357 true
358 (FileInfo.equal_hash_type
359 a_file_info.FileInfo.position_free_decl_hash
360 a_file_info'.FileInfo.position_free_decl_hash)
361 "Expected file info to be found in the naming table";
362 let a_pos' =
363 Option.value_exn (Naming_provider.get_const_pos ctx a_name)
365 Asserter.Bool_asserter.assert_equals
366 true
367 (FileInfo.equal_pos a_pos a_pos')
368 "Expected position of constant to be found in the naming table")
370 let test_context_changes_consts () =
371 run_naming_table_test
372 (fun
373 ~ctx
374 ~unbacked_naming_table:_
375 ~backed_naming_table:_
376 ~db_name:_
377 ~tmp_path:_
379 let (ctx, _entry) =
380 Provider_context.add_or_overwrite_entry_contents
381 ~ctx
382 ~path:(Relative_path.from_root ~suffix:"foo.php")
383 ~contents:{|<?hh
384 class New_qux {}
387 let (ctx, _entry) =
388 Provider_context.add_or_overwrite_entry_contents
389 ~ctx
390 ~path:(Relative_path.from_root ~suffix:"qux.php")
391 ~contents:{|<?hh
392 const int New_qux = 5;
395 Asserter.Relative_path_asserter.assert_option_equals
396 (Some (Relative_path.from_root ~suffix:"qux.php"))
397 (Naming_provider.get_const_path ctx "\\New_qux")
398 "New const in context should be visible";
399 Asserter.Relative_path_asserter.assert_option_equals
400 None
401 (Naming_provider.get_const_path ctx "\\Qux")
402 "Old, deleted const in context should NOT be visible")
404 let test_context_changes_funs () =
405 run_naming_table_test
406 (fun
407 ~ctx
408 ~unbacked_naming_table:_
409 ~backed_naming_table:_
410 ~db_name:_
411 ~tmp_path:_
413 Asserter.String_asserter.assert_option_equals
414 (Some "\\bar")
415 (Naming_provider.get_fun_canon_name ctx "\\bar")
416 "Existing function should be accessible by non-canon name \\bar";
417 Asserter.String_asserter.assert_option_equals
418 (Some "\\bar")
419 (Naming_provider.get_fun_canon_name ctx "\\BAR")
420 "Existing function should be accessible by non-canon name \\BAR";
422 let (ctx, _entry) =
423 Provider_context.add_or_overwrite_entry_contents
424 ~ctx
425 ~path:(Relative_path.from_root ~suffix:"foo.php")
426 ~contents:{|<?hh
427 class bar {}
430 let (ctx, _entry) =
431 Provider_context.add_or_overwrite_entry_contents
432 ~ctx
433 ~path:(Relative_path.from_root ~suffix:"bar.php")
434 ~contents:{|<?hh
435 function new_bar(): void {}
438 Asserter.Relative_path_asserter.assert_option_equals
439 (Some (Relative_path.from_root ~suffix:"bar.php"))
440 (Naming_provider.get_fun_path ctx "\\new_bar")
441 "New function in context should be visible";
442 Asserter.Relative_path_asserter.assert_option_equals
443 None
444 (Naming_provider.get_fun_path ctx "\\bar")
445 "Old, deleted function in context should NOT be visible";
447 Asserter.String_asserter.assert_option_equals
448 (Some "\\new_bar")
449 (Naming_provider.get_fun_canon_name ctx "\\NeW_bAr")
450 "New function in context should be accessible by canon name";
452 (* NB: under shared-memory provider, the following two tests aren't
453 useful. Sharedmem doesn't suppress canonical lookup results that
454 have been overridden by the context. (That's because sharedmem only
455 gives us back the canonical name, not the path where that canonical
456 name was defined, and without paths we can't tell whether it's been
457 overridden by context). For the sharedmem case, the caller is expected
458 to manually remove any old reverse-naming-table entries before calling
459 into the naming provider -- something that this test doesn't do.
460 Hence why it gives incorrect answers. *)
461 let expected =
462 match Provider_context.get_backend ctx with
463 | Provider_backend.Shared_memory ->
464 Some "\\bar" (* because the caller (us) is expected to clean up *)
465 | _ -> None
467 Asserter.String_asserter.assert_option_equals
468 expected
469 (Naming_provider.get_fun_canon_name ctx "\\bar")
470 "Old function in context should NOT be accessible by non-canon name \\bar";
471 Asserter.String_asserter.assert_option_equals
472 expected
473 (Naming_provider.get_fun_canon_name ctx "\\BAR")
474 "Old function in context should NOT be accessible by non-canon name \\BAR";
475 Asserter.String_asserter.assert_option_equals
476 expected
477 (Naming_provider.get_fun_canon_name ctx "\\BaR")
478 "Old function in context should NOT be accessible by non-canon name \\BaR";
481 let test_context_changes_classes () =
482 run_naming_table_test
483 (fun
484 ~ctx
485 ~unbacked_naming_table:_
486 ~backed_naming_table:_
487 ~db_name:_
488 ~tmp_path:_
490 Asserter.String_asserter.assert_option_equals
491 (Some "\\Foo")
492 (Naming_provider.get_type_canon_name ctx "\\Foo")
493 "Existing class should be accessible by non-canon name \\Foo";
494 Asserter.String_asserter.assert_option_equals
495 (Some "\\Foo")
496 (Naming_provider.get_type_canon_name ctx "\\FOO")
497 "Existing class should be accessible by non-canon name \\FOO";
499 let (ctx, _entry) =
500 Provider_context.add_or_overwrite_entry_contents
501 ~ctx
502 ~path:(Relative_path.from_root ~suffix:"foo.php")
503 ~contents:{|<?hh
504 class NewFoo {}
507 Asserter.Relative_path_asserter.assert_option_equals
508 (Some (Relative_path.from_root ~suffix:"foo.php"))
509 (Naming_provider.get_class_path ctx "\\NewFoo")
510 "New class in context should be visible";
511 Asserter.Relative_path_asserter.assert_option_equals
512 None
513 (Naming_provider.get_class_path ctx "\\Foo")
514 "Old class in context should NOT be visible";
516 Asserter.String_asserter.assert_option_equals
517 (Some "\\NewFoo")
518 (Naming_provider.get_type_canon_name ctx "\\NEWFOO")
519 "New class in context should be accessible by canon name";
521 (* NB: under shared-memory provider, the following two tests aren't
522 useful. Sharedmem doesn't suppress canonical lookup results that
523 have been overridden by the context. (That's because sharedmem only
524 gives us back the canonical name, not the path where that canonical
525 name was defined, and without paths we can't tell whether it's been
526 overridden by context). For the sharedmem case, the caller is expected
527 to manually remove any old reverse-naming-table entries before calling
528 into the naming provider -- something that this test doesn't do.
529 Hence why it gives incorrect answers. *)
530 let expected =
531 match Provider_context.get_backend ctx with
532 | Provider_backend.Shared_memory ->
533 Some "\\Foo" (* because the caller (us) is expected to clean up *)
534 | _ -> None
536 Asserter.String_asserter.assert_option_equals
537 expected
538 (Naming_provider.get_type_canon_name ctx "\\Foo")
539 "Old class in context should NOT be accessible by non-canon name \\Foo";
540 Asserter.String_asserter.assert_option_equals
541 expected
542 (Naming_provider.get_type_canon_name ctx "\\FOO")
543 "Old class in context should NOT be accessible by non-canon name \\FOO";
544 Asserter.String_asserter.assert_option_equals
545 expected
546 (Naming_provider.get_type_canon_name ctx "\\FoO")
547 "Old class in context should NOT be accessible by non-canon name \\FoO";
550 let test_context_changes_modules () =
551 run_naming_table_test
552 (fun
553 ~ctx
554 ~unbacked_naming_table:_
555 ~backed_naming_table:_
556 ~db_name:_
557 ~tmp_path:_
559 Asserter.Relative_path_asserter.assert_option_equals
560 (Some (Relative_path.from_root ~suffix:"corge.php"))
561 (Naming_provider.get_module_path ctx "Corge")
562 "Existing module Corge should be in corge.php";
563 Asserter.Relative_path_asserter.assert_option_equals
564 (Some (Relative_path.from_root ~suffix:"corge2.php"))
565 (Naming_provider.get_module_path ctx "corge")
566 "Existing module corge (lowercase) should be in corge2.php";
567 let (ctx, _entry) =
568 Provider_context.add_or_overwrite_entry_contents
569 ~ctx
570 ~path:(Relative_path.from_root ~suffix:"corge.php")
571 ~contents:{|<?hh
574 Asserter.Relative_path_asserter.assert_option_equals
575 None
576 (Naming_provider.get_module_path ctx "Corge")
577 "module Corge should be deleted";
578 Asserter.Relative_path_asserter.assert_option_equals
579 (Some (Relative_path.from_root ~suffix:"corge2.php"))
580 (Naming_provider.get_module_path ctx "corge")
581 "Existing module corge (lowercase) should be in corge2.php";
584 let test_context_changes_typedefs () =
585 run_naming_table_test
586 (fun
587 ~ctx
588 ~unbacked_naming_table:_
589 ~backed_naming_table:_
590 ~db_name:_
591 ~tmp_path:_
593 Asserter.String_asserter.assert_option_equals
594 (Some "\\Baz")
595 (Naming_provider.get_type_canon_name ctx "\\Baz")
596 "Existing typedef should be accessible by non-canon name \\Baz";
597 Asserter.String_asserter.assert_option_equals
598 (Some "\\Baz")
599 (Naming_provider.get_type_canon_name ctx "\\BAZ")
600 "Existing typedef should be accessible by non-canon name \\BAZ";
602 let (ctx, _entry) =
603 Provider_context.add_or_overwrite_entry_contents
604 ~ctx
605 ~path:(Relative_path.from_root ~suffix:"baz.php")
606 ~contents:{|<?hh
607 type NewBaz = Foo;
610 Asserter.Relative_path_asserter.assert_option_equals
611 (Some (Relative_path.from_root ~suffix:"baz.php"))
612 (Naming_provider.get_typedef_path ctx "\\NewBaz")
613 "New typedef in context should be visible";
614 Asserter.Relative_path_asserter.assert_option_equals
615 None
616 (Naming_provider.get_typedef_path ctx "\\Baz")
617 "Old typedef in context should NOT be visible";
619 Asserter.String_asserter.assert_option_equals
620 (Some "\\NewBaz")
621 (Naming_provider.get_type_canon_name ctx "\\NEWBAZ")
622 "New typedef in context should be accessible by canon name";
624 (* NB: under shared-memory provider, the following two tests aren't
625 useful. Sharedmem doesn't suppress canonical lookup results that
626 have been overridden by the context. (That's because sharedmem only
627 gives us back the canonical name, not the path where that canonical
628 name was defined, and without paths we can't tell whether it's been
629 overridden by context). For the sharedmem case, the caller is expected
630 to manually remove any old reverse-naming-table entries before calling
631 into the naming provider -- something that this test doesn't do.
632 Hence why it gives incorrect answers. *)
633 let expected =
634 match Provider_context.get_backend ctx with
635 | Provider_backend.Shared_memory ->
636 Some "\\Baz" (* because the caller (us) is expected to clean up *)
637 | _ -> None
639 Asserter.String_asserter.assert_option_equals
640 expected
641 (Naming_provider.get_type_canon_name ctx "\\Baz")
642 "Old typedef in context should NOT be accessible by non-canon name \\Baz";
643 Asserter.String_asserter.assert_option_equals
644 expected
645 (Naming_provider.get_type_canon_name ctx "\\BAZ")
646 "Old typedef in context should NOT be accessible by non-canon name \\BAZ";
647 Asserter.String_asserter.assert_option_equals
648 expected
649 (Naming_provider.get_type_canon_name ctx "\\BaZ")
650 "Old typedef in context should NOT be accessible by non-canon name \\BaZ";
653 let test_naming_table_hash () =
654 List.iter [0; -1; 1; 200; -200; Int.max_value; Int.min_value] ~f:(fun i ->
655 let dep = Typing_deps.Dep.of_debug_string (string_of_int i) in
656 let hash = Typing_deps.Dep.to_int64 dep in
657 (* "%16x" on a negative integer will produce a hex version as if it were unsigned, e.g. -2 is printed as 7ffffffffffffffe rather than -0000000000000002. *)
658 let i_str = Printf.sprintf "0x%016x" i in
659 let hash_str = Printf.sprintf "0x%016Lx" hash in
660 Asserter.String_asserter.assert_equals
661 i_str
662 hash_str
663 "Expected 64bit hash to be same as int hash");
665 let foo_dep = Typing_deps.Dep.Type "\\Foo" in
666 let foo_dep_hash =
667 Typing_deps.Dep.make foo_dep |> Typing_deps.Dep.to_hex_string
669 Asserter.String_asserter.assert_equals
670 "0x4cd17f7c3d7b6feb"
671 foo_dep_hash
672 "Expected foo dep hash to be correct (this test must be updated if the hashing logic changes)";
674 true
676 let test_naming_table_query_by_dep_hash () =
677 run_naming_table_test
678 (fun
679 ~ctx
680 ~unbacked_naming_table:_
681 ~backed_naming_table
682 ~db_name:_
683 ~tmp_path:_
685 let db_path =
686 Db_path_provider.get_naming_db_path (Provider_context.get_backend ctx)
688 let db_path = Option.value_exn db_path in
689 Asserter.Relative_path_asserter.assert_option_equals
690 (Some (Relative_path.from_root ~suffix:"qux.php"))
691 (Typing_deps.Dep.GConst "\\Qux"
692 |> Typing_deps.Dep.make
693 |> Naming_sqlite.get_path_by_64bit_dep db_path
694 |> Option.map ~f:fst)
695 "Look up const by dep hash should return file path";
696 Asserter.Relative_path_asserter.assert_option_equals
697 None
698 (Typing_deps.Dep.GConst "\\Nonexistent"
699 |> Typing_deps.Dep.make
700 |> Naming_sqlite.get_path_by_64bit_dep db_path
701 |> Option.map ~f:fst)
702 "Look up non-existent const by dep hash should return nothing";
704 Asserter.Relative_path_asserter.assert_option_equals
705 (Some (Relative_path.from_root ~suffix:"bar.php"))
706 (Typing_deps.Dep.Fun "\\bar"
707 |> Typing_deps.Dep.make
708 |> Naming_sqlite.get_path_by_64bit_dep db_path
709 |> Option.map ~f:fst)
710 "Look up fun by dep hash should return file path";
711 Asserter.Relative_path_asserter.assert_option_equals
712 None
713 (Typing_deps.Dep.Fun "\\nonexistent"
714 |> Typing_deps.Dep.make
715 |> Naming_sqlite.get_path_by_64bit_dep db_path
716 |> Option.map ~f:fst)
717 "Look up non-existent fun by dep hash should return nothing";
719 Asserter.Relative_path_asserter.assert_option_equals
720 (Some (Relative_path.from_root ~suffix:"foo.php"))
721 (Typing_deps.Dep.Type "\\Foo"
722 |> Typing_deps.Dep.make
723 |> Naming_sqlite.get_path_by_64bit_dep db_path
724 |> Option.map ~f:fst)
725 "Look up class by dep hash should return file path";
726 Asserter.Relative_path_asserter.assert_option_equals
727 None
728 (Typing_deps.Dep.Type "\\nonexistent"
729 |> Typing_deps.Dep.make
730 |> Naming_sqlite.get_path_by_64bit_dep db_path
731 |> Option.map ~f:fst)
732 "Look up non-existent class by dep hash should return nothing";
734 Asserter.Relative_path_asserter.assert_option_equals
735 (Some (Relative_path.from_root ~suffix:"baz.php"))
736 (Typing_deps.Dep.Type "\\Baz"
737 |> Typing_deps.Dep.make
738 |> Naming_sqlite.get_path_by_64bit_dep db_path
739 |> Option.map ~f:fst)
740 "Look up class by dep hash should return file path";
741 Asserter.Relative_path_asserter.assert_option_equals
742 None
743 (Typing_deps.Dep.Type "\\nonexistent"
744 |> Typing_deps.Dep.make
745 |> Naming_sqlite.get_path_by_64bit_dep db_path
746 |> Option.map ~f:fst)
747 "Look up non-existent typedef by dep hash should return nothing";
749 Asserter.Relative_path_asserter.assert_list_equals
750 [Relative_path.from_root ~suffix:"qux.php"]
751 (Typing_deps.Dep.GConst "\\Qux"
752 |> Typing_deps.Dep.make
753 |> Typing_deps.DepSet.singleton
754 |> Naming_table.get_64bit_dep_set_files backed_naming_table
755 |> Relative_path.Set.elements)
756 "Bulk lookup for const should be correct";
757 Asserter.Relative_path_asserter.assert_list_equals
758 [Relative_path.from_root ~suffix:"bar.php"]
759 (Typing_deps.Dep.Fun "\\bar"
760 |> Typing_deps.Dep.make
761 |> Typing_deps.DepSet.singleton
762 |> Naming_table.get_64bit_dep_set_files backed_naming_table
763 |> Relative_path.Set.elements)
764 "Bulk lookup for fun should be correct";
765 Asserter.Relative_path_asserter.assert_list_equals
766 [Relative_path.from_root ~suffix:"baz.php"]
767 (Typing_deps.Dep.Type "\\Baz"
768 |> Typing_deps.Dep.make
769 |> Typing_deps.DepSet.singleton
770 |> Naming_table.get_64bit_dep_set_files backed_naming_table
771 |> Relative_path.Set.elements)
772 "Bulk lookup for class should be correct";
774 Asserter.Relative_path_asserter.assert_list_equals
776 Relative_path.from_root ~suffix:"bar.php";
777 Relative_path.from_root ~suffix:"baz.php";
778 Relative_path.from_root ~suffix:"qux.php";
780 (Typing_deps.DepSet.make ()
781 |> Typing_deps.DepSet.union
782 (Typing_deps.Dep.GConst "\\Qux"
783 |> Typing_deps.Dep.make
784 |> Typing_deps.DepSet.singleton)
785 |> Typing_deps.DepSet.union
786 (Typing_deps.Dep.Fun "\\bar"
787 |> Typing_deps.Dep.make
788 |> Typing_deps.DepSet.singleton)
789 |> Typing_deps.DepSet.union
790 (Typing_deps.Dep.Type "\\Baz"
791 |> Typing_deps.Dep.make
792 |> Typing_deps.DepSet.singleton)
793 |> Naming_table.get_64bit_dep_set_files backed_naming_table
794 |> Relative_path.Set.elements)
795 "Bulk lookup for multiple elements should be correct";
797 (* Simulate moving \Baz from baz.php to bar.php. *)
798 let baz_file_info = FileInfo.empty_t in
799 let bar_file_info =
801 (* Might raise {!Naming_table.File_info_not_found} *)
802 (Naming_table.get_file_info_exn
803 backed_naming_table
804 (Relative_path.from_root ~suffix:"bar.php"))
805 with
806 FileInfo.ids =
808 FileInfo.empty_ids with
809 FileInfo.classes =
811 FileInfo.
813 pos =
814 FileInfo.File
815 ( FileInfo.Class,
816 Relative_path.from_root ~suffix:"bar.php" );
817 name = "\\Baz";
818 decl_hash = None;
819 sort_text = None;
825 let new_naming_table = backed_naming_table in
826 let new_naming_table =
827 Naming_table.update
828 new_naming_table
829 (Relative_path.from_root ~suffix:"baz.php")
830 baz_file_info
832 let new_naming_table =
833 Naming_table.update
834 new_naming_table
835 (Relative_path.from_root ~suffix:"bar.php")
836 bar_file_info
838 Asserter.Relative_path_asserter.assert_list_equals
839 [Relative_path.from_root ~suffix:"bar.php"]
840 (Typing_deps.Dep.Type "\\Baz"
841 |> Typing_deps.Dep.make
842 |> Typing_deps.DepSet.singleton
843 |> Naming_table.get_64bit_dep_set_files new_naming_table
844 |> Relative_path.Set.elements)
845 "\\Baz should now be located in bar.php";
849 let () =
850 let config =
851 SharedMem.
853 global_size = 1024;
854 heap_size = 1024 * 1024;
855 hash_table_pow = 10;
856 shm_dirs = [];
857 shm_use_sharded_hashtbl = false;
858 shm_cache_size = -1;
859 shm_min_avail = 0;
860 log_level = 0;
861 sample_rate = 0.0;
862 compression = 0;
865 let (_ : SharedMem.handle) = SharedMem.init config ~num_workers:0 in
866 EventLogger.init_fake ();
867 Hh_logger.Level.set_min_level_stderr Hh_logger.Level.Warn;
868 Unit_test.run_all
870 ("test_get_pos", test_get_pos);
871 ("test_get_canon_name", test_get_canon_name);
872 ("test_remove", test_remove);
873 ("test_get_sqlite_paths", test_get_sqlite_paths);
874 ("test_local_changes", test_local_changes);
875 ("test_context_changes_consts", test_context_changes_consts);
876 ("test_context_changes_funs", test_context_changes_funs);
877 ("test_context_changes_classes", test_context_changes_classes);
878 ("test_context_changes_typedefs", test_context_changes_typedefs);
879 ("test_context_changes_modules", test_context_changes_modules);
880 ("test_naming_table_hash", test_naming_table_hash);
881 ( "test_naming_table_query_by_dep_hash",
882 test_naming_table_query_by_dep_hash );