From 04853dad38449e1a8a140badfc7e7a06da2f5d69 Mon Sep 17 00:00:00 2001 From: Chaoqiang Deng Date: Tue, 22 Feb 2022 10:19:24 -0800 Subject: [PATCH] Organize the unit tests for global_write_check Summary: To replace the original single large test case, here we create several tiny unit test cases for primitives, collections, objects, memoized functions, anonymous functions and so on. - Notice that the cases where our current analyzer does not handle well are marked by "To do" in the comments. Reviewed By: jamesjwu Differential Revision: D34180838 fbshipit-source-id: c9096e081d96fd0c8a762dcba0b4c692894e60ca --- .../global_write_check/test_anonymous.php | 29 +++++++++ .../global_write_check/test_anonymous.php.exp | 6 ++ .../typecheck/global_write_check/test_basics.php | 50 +++++++++++++++ .../global_write_check/test_basics.php.exp | 20 ++++++ .../global_write_check/test_collection.php | 72 ++++++++++++++++++++++ .../global_write_check/test_collection.php.exp | 26 ++++++++ .../global_write_check/test_control_flow.php | 33 ++++++++++ .../global_write_check/test_control_flow.php.exp | 6 ++ .../typecheck/global_write_check/test_memoized.php | 48 +++++++++++++++ .../global_write_check/test_memoized.php.exp | 8 +++ .../typecheck/global_write_check/test_object.php | 51 +++++++++++++++ .../global_write_check/test_object.php.exp | 16 +++++ .../global_write_check/test_primitive.php | 45 ++++++++++++++ .../global_write_check/test_primitive.php.exp | 12 ++++ 14 files changed, 422 insertions(+) create mode 100644 hphp/hack/test/typecheck/global_write_check/test_anonymous.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_anonymous.php.exp create mode 100644 hphp/hack/test/typecheck/global_write_check/test_basics.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_basics.php.exp create mode 100644 hphp/hack/test/typecheck/global_write_check/test_collection.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_collection.php.exp create mode 100644 hphp/hack/test/typecheck/global_write_check/test_control_flow.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_control_flow.php.exp create mode 100644 hphp/hack/test/typecheck/global_write_check/test_memoized.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_memoized.php.exp create mode 100644 hphp/hack/test/typecheck/global_write_check/test_object.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_object.php.exp create mode 100644 hphp/hack/test/typecheck/global_write_check/test_primitive.php create mode 100644 hphp/hack/test/typecheck/global_write_check/test_primitive.php.exp diff --git a/hphp/hack/test/typecheck/global_write_check/test_anonymous.php b/hphp/hack/test/typecheck/global_write_check/test_anonymous.php new file mode 100644 index 00000000000..8d4bd0de196 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_anonymous.php @@ -0,0 +1,29 @@ +> public static Bar $bar; +} + +class Test { + public function test_method_call(): void { + $a = Foo::$bar; + $fun = (int $val): Bar ==> { + Foo::$static_prop = 2; // A global variable is written. + $a->prop = $val; // A global variable is written. + + $a = new Bar(); + $a->prop = $val; + + return $a; + }; + $a->prop = 2; // A global variable is written. + + $b = $fun(3); + $b->prop = 4; + } +} diff --git a/hphp/hack/test/typecheck/global_write_check/test_anonymous.php.exp b/hphp/hack/test/typecheck/global_write_check/test_anonymous.php.exp new file mode 100644 index 00000000000..5b736eb1eb6 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_anonymous.php.exp @@ -0,0 +1,6 @@ +File "test_anonymous.php", line 16, characters 7-27: +A global variable is written. (Typing[4459]) +File "test_anonymous.php", line 17, characters 7-21: +A global variable is written. (Typing[4459]) +File "test_anonymous.php", line 24, characters 5-16: +A global variable is written. (Typing[4459]) diff --git a/hphp/hack/test/typecheck/global_write_check/test_basics.php b/hphp/hack/test/typecheck/global_write_check/test_basics.php new file mode 100644 index 00000000000..fdcfe261ed8 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_basics.php @@ -0,0 +1,50 @@ +> public static Bar $bar; +} + +function call_mixed(mixed $x): void {} + +function test_fun_call(): Bar { + $a = Foo::$bar; + $a->prop = 2; // A global variable is written. + return $a; // A global variable is passed to (or returned from) a function call. +} + +class Test { + private static int $static_prop = 0; + + public function test_method_call(): void { + self::$static_prop = 1; // A global variable is written. + + Foo::$static_prop = 2; // A global variable is written. + Foo::$static_prop++; // A global variable is written. + + (Foo::$bar)->prop = 2; // A global variable is written. + Foo::$bar = new Bar(); // A global variable is written. + + $a = Foo::$static_prop; + $a = 2; + $a++; + + $b = Foo::$bar; + $b->prop = 2; // A global variable is written. + $b->prop++; // A global variable is written. + + $c = $b; + call_mixed($c); // A global variable is passed to (or returned from) a function call. + call_mixed(Foo::$static_prop); + + $d = $c->prop; + $d = 3; + + $b = new Bar(); + $b->prop = 2; + } +} diff --git a/hphp/hack/test/typecheck/global_write_check/test_basics.php.exp b/hphp/hack/test/typecheck/global_write_check/test_basics.php.exp new file mode 100644 index 00000000000..a02d73446a8 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_basics.php.exp @@ -0,0 +1,20 @@ +File "test_basics.php", line 16, characters 3-14: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 17, characters 10-11: +A global variable is passed to (or returned from) a function call. (Typing[4460]) +File "test_basics.php", line 24, characters 5-26: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 26, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 27, characters 5-23: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 29, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 30, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 37, characters 5-16: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 38, characters 5-14: +A global variable is written. (Typing[4459]) +File "test_basics.php", line 41, characters 16-17: +A global variable is passed to (or returned from) a function call. (Typing[4460]) diff --git a/hphp/hack/test/typecheck/global_write_check/test_collection.php b/hphp/hack/test/typecheck/global_write_check/test_collection.php new file mode 100644 index 00000000000..92aa9a40a89 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_collection.php @@ -0,0 +1,72 @@ +> public static Bar $static_bar; + + public static vec $static_vec_int = vec[0, 1, 2]; + <<__LateInit>> public static vec $static_vec_bar; + + public static function get_bar(): Bar { + return self::$static_bar; // A global variable is passed to (or returned from) a function call. + } + + public static function set_bar(Bar $b): void { + self::$static_bar = $b; // A global variable is written. + } + + public static function get_vec_int(): vec { + return self::$static_vec_int; + } + + public static function set_vec_int(vec $vi): void { + self::$static_vec_int = $vi; // A global variable is written. + } + + public static function get_vec_bar(): vec { + return self::$static_vec_bar; // A global variable is passed to (or returned from) a function call. + } + + public static function set_vec_bar(vec $vb): void { + self::$static_vec_bar = $vb; // A global variable is written. + } +} + +class Test { + public function test_method_call(): void { + Foo::$static_bar = new Bar(); // A global variable is written. + Foo::set_bar(new Bar()); + $b = Foo::$static_bar; + $b->prop = 2; // A global variable is written. + + Foo::$static_vec_int = vec[3, 4, 5]; // A global variable is written. + Foo::set_vec_int(vec[3, 4, 5]); + $c = Foo::$static_vec_int; + $c[0] = 0; + $c = vec[3, 4, 5]; + Foo::$static_vec_int[0] = 0; + + Foo::$static_vec_bar = vec[new Bar()]; // A global variable is written. + Foo::set_vec_bar(vec[new Bar()]); + $d = Foo::$static_vec_bar; + $d[0]->prop = 2; // A global variable is written. + $d = vec[new Bar()]; + $d[0]->prop = 2; + Foo::$static_vec_bar[0]->prop = 2; // A global variable is written. + + $e = shape('id' => 1, 'object' => Foo::$static_bar); + $e['object'] = Foo::$static_bar; + $e['object']->prop = 2; // A global variable is written. + $e['id'] = 2; + $e['object']->prop = 2; // To do: raise an error "A global variable is written." + + $f = vec[new Bar()]; + $f[] = Foo::$static_bar; + $f[1]->prop = 2; // A global variable is written. + $f[0] = new Bar(); + $f[1]->prop = 2; // To do: raise an error "A global variable is written." + } +} diff --git a/hphp/hack/test/typecheck/global_write_check/test_collection.php.exp b/hphp/hack/test/typecheck/global_write_check/test_collection.php.exp new file mode 100644 index 00000000000..bcd7ecb9361 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_collection.php.exp @@ -0,0 +1,26 @@ +File "test_collection.php", line 14, characters 12-28: +A global variable is passed to (or returned from) a function call. (Typing[4460]) +File "test_collection.php", line 18, characters 5-26: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 26, characters 5-31: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 30, characters 12-32: +A global variable is passed to (or returned from) a function call. (Typing[4460]) +File "test_collection.php", line 34, characters 5-31: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 40, characters 5-32: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 43, characters 5-16: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 45, characters 5-39: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 52, characters 5-41: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 55, characters 5-19: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 58, characters 5-37: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 62, characters 5-26: +A global variable is written. (Typing[4459]) +File "test_collection.php", line 68, characters 5-19: +A global variable is written. (Typing[4459]) diff --git a/hphp/hack/test/typecheck/global_write_check/test_control_flow.php b/hphp/hack/test/typecheck/global_write_check/test_control_flow.php new file mode 100644 index 00000000000..05434a737b8 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_control_flow.php @@ -0,0 +1,33 @@ +> public static Bar $bar; +} + +class Test { + public function test_method_call(): void { + (Foo::$bar)->prop = 1; // A global variable is written. + + $x = new Bar(); + if (false) {$x = Foo::$bar;} + $x->prop = 1; // A global variable is written. + + $y = Foo::$bar; + if (false) {$y = new Bar();} + $y->prop = 1; // A global variable is written. + + $z = new Bar(); + if (false) { + $z = Foo::$bar; + $z->prop = 1; // A global variable is written. + } else { + $z = new Bar(); + $z->prop = 2; + } + $z->prop = 3; // A global variable is written. + } +} diff --git a/hphp/hack/test/typecheck/global_write_check/test_control_flow.php.exp b/hphp/hack/test/typecheck/global_write_check/test_control_flow.php.exp new file mode 100644 index 00000000000..0373700b306 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_control_flow.php.exp @@ -0,0 +1,6 @@ +File "test_control_flow.php", line 13, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_control_flow.php", line 17, characters 5-16: +A global variable is written. (Typing[4459]) +File "test_control_flow.php", line 26, characters 7-18: +A global variable is written. (Typing[4459]) diff --git a/hphp/hack/test/typecheck/global_write_check/test_memoized.php b/hphp/hack/test/typecheck/global_write_check/test_memoized.php new file mode 100644 index 00000000000..dba5280f47d --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_memoized.php @@ -0,0 +1,48 @@ +> public static Bar $bar; + + <<__Memoize>> + public static function foo_method_memoized(): int { + return self::$static_prop; + } + + <<__MemoizeLSB>> + public static function foo_method_memoized_lsb(): Bar { + return self::$bar; // A global variable is passed to (or returned from) a function call. + } +} + +<<__Memoize>> +function fun_memoized(): Bar { + return new Bar(); +} + +<<__Memoize>> +function fun_memoized_vec_int(): vec { + return vec[1, 2, 3]; +} + +class Test { + public function test_method_call(): void { + (Foo::$bar)->prop = 1; // A global variable is written. + + $a = Foo::foo_method_memoized(); + $a = 2; + + $b = Foo::foo_method_memoized_lsb(); + $b->prop = 2; // A global variable is written. + + $c = fun_memoized(); + $c->prop = 2; // A global variable is written. + + $d = fun_memoized_vec_int(); + $d[0] = 2; + } +} diff --git a/hphp/hack/test/typecheck/global_write_check/test_memoized.php.exp b/hphp/hack/test/typecheck/global_write_check/test_memoized.php.exp new file mode 100644 index 00000000000..6444b1ac0a4 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_memoized.php.exp @@ -0,0 +1,8 @@ +File "test_memoized.php", line 18, characters 12-21: +A global variable is passed to (or returned from) a function call. (Typing[4460]) +File "test_memoized.php", line 34, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_memoized.php", line 40, characters 5-16: +A global variable is written. (Typing[4459]) +File "test_memoized.php", line 43, characters 5-16: +A global variable is written. (Typing[4459]) diff --git a/hphp/hack/test/typecheck/global_write_check/test_object.php b/hphp/hack/test/typecheck/global_write_check/test_object.php new file mode 100644 index 00000000000..4e518842ff9 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_object.php @@ -0,0 +1,51 @@ +prop; + } + + public function set_prop(int $i): void { + $this->prop = $i; + } +} + +class Baz { + <<__LateInit>> public Bar $bar1; + <<__LateInit>> public Bar $bar2; +} + +class Foo { + <<__LateInit>> public static Bar $bar; +} + +class Test { + public function test_method_call(): void { + Foo::$bar = new Bar(); // A global variable is written. + (Foo::$bar)->prop = 1; // A global variable is written. + + $a = Foo::$bar; + $a->prop = 1; // A global variable is written. + $a->set_prop(1); // To do: raise an error "A global variable is written." + + $b = $a->prop; + $b = 2; + + $a = new Bar(); + $a->prop = 2; + + $c = new Baz(); + $c->bar1 = new Bar(); + $c->bar1->prop = 1; + + $c->bar2 = Foo::$bar; + $c->bar2->prop = 1; // A global variable is written. + $c->bar1->prop = 1; // A global variable is written. To do: remove this error. + + $c->bar1 = new Bar(); // A global variable is written. To do: remove this error. + $c->bar2->prop = 1; // A global variable is written. + $c->bar1->prop = 1; // A global variable is written. To do: remove this error. + } +} diff --git a/hphp/hack/test/typecheck/global_write_check/test_object.php.exp b/hphp/hack/test/typecheck/global_write_check/test_object.php.exp new file mode 100644 index 00000000000..0e3ea8ac810 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_object.php.exp @@ -0,0 +1,16 @@ +File "test_object.php", line 26, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_object.php", line 27, characters 5-25: +A global variable is written. (Typing[4459]) +File "test_object.php", line 30, characters 5-16: +A global variable is written. (Typing[4459]) +File "test_object.php", line 44, characters 5-22: +A global variable is written. (Typing[4459]) +File "test_object.php", line 45, characters 5-22: +A global variable is written. (Typing[4459]) +File "test_object.php", line 47, characters 5-24: +A global variable is written. (Typing[4459]) +File "test_object.php", line 48, characters 5-22: +A global variable is written. (Typing[4459]) +File "test_object.php", line 49, characters 5-22: +A global variable is written. (Typing[4459]) diff --git a/hphp/hack/test/typecheck/global_write_check/test_primitive.php b/hphp/hack/test/typecheck/global_write_check/test_primitive.php new file mode 100644 index 00000000000..5989fd710e5 --- /dev/null +++ b/hphp/hack/test/typecheck/global_write_check/test_primitive.php @@ -0,0 +1,45 @@ +