Skip to content

Commit 19967cc

Browse files
frank-emrichmeta-codesync[bot]
authored andcommitted
only return files actually containing test classes
Summary: This diff ensures that `hh --find-my-tests` will only return files that actually contain a `WWWTest`. Since this is the only test framework we are looking at for the time being, this avoids some skew when comparing our test selection approach against what Testinfra does. Reviewed By: madgen Differential Revision: D83703465 fbshipit-source-id: 071e0e9caa30b97defe5793b61e6d210daf81170
1 parent c3aa785 commit 19967cc

File tree

13 files changed

+86
-27
lines changed

13 files changed

+86
-27
lines changed

hphp/hack/src/server/serverFindMyTests.ml

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,53 @@ type member = Method of string
1414
let findrefs_member_of_member = function
1515
| Method m -> SearchTypes.Find_refs.Method m
1616

17-
let is_test_file path =
18-
Option.is_some (String.substr_index path ~pattern:"/__tests__/")
17+
let supported_test_framework_classes = SSet.of_list ["WWWTest"]
1918

2019
let strip_ns results = List.map results ~f:(fun (s, p) -> (Utils.strip_ns s, p))
2120

21+
let is_test_file ctx file_path file_nast =
22+
let is_test_class class_name =
23+
match Decl_provider.get_class ctx class_name with
24+
| Decl_entry.DoesNotExist ->
25+
failwith
26+
(Printf.sprintf
27+
"Internal error: Could not find class %s, even though we encountered it during traversal"
28+
class_name)
29+
| NotYetAvailable ->
30+
failwith
31+
(Printf.sprintf
32+
"Internal error: Class %s, marked as not yet available"
33+
class_name)
34+
| Found class_ ->
35+
let ancestors = Folded_class.all_ancestor_names class_ in
36+
List.exists ancestors ~f:(fun ancestor ->
37+
SSet.mem (Utils.strip_ns ancestor) supported_test_framework_classes)
38+
in
39+
40+
match String.substr_index file_path ~pattern:"/__tests__/" with
41+
| None -> false
42+
| Some _ ->
43+
let classes_in_file =
44+
let visitor =
45+
object
46+
inherit [_] Aast.reduce
47+
48+
method! on_class_ _ctx class_ =
49+
SSet.singleton (Ast_defs.get_id class_.c_name)
50+
51+
method! on_method_ _ctx _ = SSet.empty
52+
53+
method! on_fun_ _ctx _ = SSet.empty
54+
55+
method plus = SSet.union
56+
57+
method zero = SSet.empty
58+
end
59+
in
60+
visitor#on_program () file_nast
61+
in
62+
SSet.exists is_test_class classes_in_file
63+
2264
let search ctx target include_defs ~files genv =
2365
List.iter files ~f:(fun file ->
2466
Hh_logger.debug
@@ -109,16 +151,8 @@ type result_entry = ServerCommandTypes.Find_my_tests.result_entry
109151
Ideally, FindRefsService (or an alternative to it) would give us the enclosing SymbolDefinition
110152
directly, but that would require piping that information through IdentifySymbolService.
111153
*)
112-
let enclosing_def_of_symbol_occurrence ctx (symbol_occurrence_pos : Pos.t) :
113-
symbol_def option =
114-
(* We could implement all this without NASTs, but just CSTs and their
115-
Full_fidelity_positioned_syntax.parentage function.
116-
117-
But those never seem to be cached, whereas the NAST may still be in cache after we just
118-
constructed the TAST in FindRefsService. *)
119-
let path = Pos.filename symbol_occurrence_pos in
120-
let nast = Ast_provider.get_ast ~full:true ctx path in
121-
154+
let enclosing_def_of_symbol_occurrence
155+
(symbol_occurrence_pos : Pos.t) symbol_occurrence_nast : symbol_def option =
122156
let visitor =
123157
object
124158
inherit [_] Aast.reduce as super
@@ -149,7 +183,7 @@ let enclosing_def_of_symbol_occurrence ctx (symbol_occurrence_pos : Pos.t) :
149183
| (Some _, _) -> r1
150184
end
151185
in
152-
visitor#on_program None nast
186+
visitor#on_program None symbol_occurrence_nast
153187

154188
(**
155189
Find references to the given symbol.
@@ -172,13 +206,22 @@ let get_references
172206
env
173207
in
174208
let resolve_found_position (acc_symbol_defs, acc_files) (_, referencing_pos) =
175-
let file = Pos.filename referencing_pos |> Relative_path.suffix in
176-
if is_test_file file then
209+
let relative_path = Pos.filename referencing_pos in
210+
let path = Relative_path.suffix relative_path in
211+
212+
(* We could implement all of our traversals without NASTs, but just CSTs and their
213+
Full_fidelity_positioned_syntax.parentage function.
214+
215+
But those never seem to be cached, whereas the NAST may still be in cache after we just
216+
constructed the TAST in FindRefsService. *)
217+
let nast = Ast_provider.get_ast ~full:true ctx relative_path in
218+
219+
if is_test_file ctx path nast then
177220
Result.Ok
178221
( acc_symbol_defs,
179222
(Pos.to_absolute referencing_pos |> Pos.filename) :: acc_files )
180223
else
181-
match enclosing_def_of_symbol_occurrence ctx referencing_pos with
224+
match enclosing_def_of_symbol_occurrence referencing_pos nast with
182225
| Some referencing_def ->
183226
Result.Ok (referencing_def :: acc_symbol_defs, acc_files)
184227
| None ->
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?hh
2+
3+
class WWWTest {}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?hh
2+
3+
4+
// Notably, this does not extend WWWTest
5+
class A_AlsoNotATest {
6+
public function testTarget(A_Sub $a): void {
7+
$a->target();
8+
}
9+
}

hphp/hack/test/integration/data/find_my_tests_repo/a/__tests__/A_MiddleTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class A_MiddleTest {
3+
class A_MiddleTest extends WWWTest {
44

55
public function testTarget(A_Middle $a): void {
66
$a->target();

hphp/hack/test/integration/data/find_my_tests_repo/a/__tests__/A_SiblingTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class A_SiblingTest {
3+
class A_SiblingTest extends WWWTest {
44

55
public function testTarget(A_Sibling $a): void {
66
// We statically know that this will not call A_Mid::target

hphp/hack/test/integration/data/find_my_tests_repo/a/__tests__/A_SubNoOverrideTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class A_SubNoOverrideTest {
3+
class A_SubNoOverrideTest extends WWWTest {
44

55
public function testTarget(A_SubNoOverride $a): void {
66
// We statically know that this may call A_Mid::target (directly)

hphp/hack/test/integration/data/find_my_tests_repo/a/__tests__/A_SubTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class A_SubTest {
3+
class A_SubTest extends WWWTest {
44

55
public function testTarget(A_Sub $a): void {
66
// We statically know that this isn't calling A_Mid::target (directly),

hphp/hack/test/integration/data/find_my_tests_repo/a/__tests__/A_SuperTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class A_SuperTest {
3+
class A_SuperTest extends WWWTest {
44

55
public function testTarget(A_Super $a): void {
66
$a->target();

hphp/hack/test/integration/data/find_my_tests_repo/b/__tests__/B_UsesDist1Test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class B_UsesDist1Test {
3+
class B_UsesDist1Test extends WWWTest {
44
public function testUsesDist1(B_Def $b): void {
55
$b->foo();
66
}

hphp/hack/test/integration/data/find_my_tests_repo/b/__tests__/B_UsesDist2Test.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?hh
22

3-
class B_UsesDist2Test {
3+
class B_UsesDist2Test extends WWWTest {
44
public function testUsesDist2(B_Def $b): void {
55
// calling the dist1 function means total dist is 2
66
B_Uses::usesDist1($b);

0 commit comments

Comments
 (0)