Skip to content

Commit

Permalink
Tests and changes for decorators (#193)
Browse files Browse the repository at this point in the history
- Decorator testing.
- Actually capture the decorated function for @tf.function decorated
functions.
- Add `pytest.mark.skip` summary.
- Use pytest summary for all Python analysis. There are some decorators
it may work for.
  - Test pytest decorator.
  • Loading branch information
khatchad committed May 26, 2024
1 parent 859e413 commit 60955d6
Show file tree
Hide file tree
Showing 20 changed files with 404 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -814,6 +814,12 @@ public void testDecorator10()
test("tf2_testing_decorator10.py", "returned", 1, 1, 2);
}

@Test
public void testDecorator11()
throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
test("tf2_testing_decorator11.py", "C.returned", 1, 1, 3);
}

@Test
public void testDataset()
throws ClassHierarchyException, IllegalArgumentException, CancelException, IOException {
Expand Down Expand Up @@ -3621,6 +3627,94 @@ public void testAbstractMethod2() throws ClassHierarchyException, CancelExceptio
test("tf2_test_abstract_method2.py", "C.f", 1, 1, 3);
}

@Test
public void testAbstractMethod3() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_abstract_method3.py", "C.f", 1, 1, 3);
}

@Test
public void testDecoratedMethod() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod2() throws ClassHierarchyException, CancelException, IOException {
// NOTE: Change to 0, 0 once https://github.com/wala/ML/issues/147 is fixed.
test("tf2_test_decorated_method2.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod3() throws ClassHierarchyException, CancelException, IOException {
// NOTE: Change to 0, 0 once https://github.com/wala/ML/issues/147 is fixed.
test("tf2_test_decorated_method3.py", "raffi", 1, 1, 2);
}

@Test
public void testDecoratedMethod4() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method4.py", "raffi", 1, 1, 2);
}

@Test
public void testDecoratedMethod5() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method5.py", "raffi", 1, 1, 2);
}

@Test
public void testDecoratedMethod6() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method6.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod7() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method7.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod8() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method8.py", "f", 1, 1, 2);
}

/** This decorator isn't defined. Thus, we shouldn't have a CG node for it. */
@Test
public void testDecoratedMethod9() throws ClassHierarchyException, CancelException, IOException {
// NOTE: Change to 0, 0 once https://github.com/wala/ML/issues/147 is fixed.
test("tf2_test_decorated_method9.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod10() throws ClassHierarchyException, CancelException, IOException {
// NOTE: Change to 0, 0 once https://github.com/wala/ML/issues/147 is fixed.
test("tf2_test_decorated_method10.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod11() throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_method11.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod12() throws ClassHierarchyException, CancelException, IOException {
// NOTE: Change to 0, 0 once https://github.com/wala/ML/issues/147 is fixed.
test("tf2_test_decorated_method12.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedMethod13() throws ClassHierarchyException, CancelException, IOException {
// NOTE: Change to 0, 0 once https://github.com/wala/ML/issues/147 is fixed.
test("tf2_test_decorated_method13.py", "f", 1, 1, 2);
}

@Test
public void testDecoratedFunctions()
throws ClassHierarchyException, CancelException, IOException {
test("tf2_test_decorated_functions.py", "dummy_fun", 1, 1, 2);
test("tf2_test_decorated_functions.py", "dummy_test", 1, 1, 2);
test("tf2_test_decorated_functions.py", "test_function", 1, 1, 2);
test("tf2_test_decorated_functions.py", "test_function2", 1, 1, 2);
test("tf2_test_decorated_functions.py", "test_function3", 1, 1, 2);
test("tf2_test_decorated_functions.py", "test_function4", 1, 1, 2);
}

private void test(
String filename,
String functionName,
Expand Down
24 changes: 23 additions & 1 deletion com.ibm.wala.cast.python.ml/data/tensorflow.xml
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,12 @@
<putfield class="LRoot" field="from_row_starts" fieldType="LRoot" ref="RaggedTensor" value="from_row_starts" />
<new def="from_value_rowids" class="Ltensorflow/functions/from_value_rowids" />
<putfield class="LRoot" field="from_value_rowids" fieldType="LRoot" ref="RaggedTensor" value="from_value_rowids" />
<new def="autograph" class="Lobject" />
<putfield class="LRoot" field="autograph" fieldType="LRoot" ref="x" value="autograph" />
<putfield class="LRoot" field="experimental" fieldType="LRoot" ref="autograph" value="experimental" />
<!-- https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/autograph/experimental/do_not_convert -->
<new def="do_not_convert" class="Ltensorflow/class/do_not_convert" />
<putfield class="LRoot" field="do_not_convert" fieldType="LRoot" ref="experimental" value="do_not_convert" />
<return value="x" />
</method>
</class>
Expand All @@ -276,7 +282,7 @@
</class>
<class name="function" allocatable="true">
<!-- These parameters are from TensorFlow v.2.9 https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/function -->
<method name="do" descriptor="()LRoot;" numArgs="10" paramNames="func input_signature autograph jit_compile reduce_retracing experimental_implements experimental_autograph_options experimental_relax_shapes experimental_compile experimental_follow_type_hints">
<method name="do" descriptor="()LRoot;" numArgs="11" paramNames="self func input_signature autograph jit_compile reduce_retracing experimental_implements experimental_autograph_options experimental_relax_shapes experimental_compile experimental_follow_type_hints">
<new def="params" class="Ltensorflow/class/Function" />
<putfield class="LRoot" field="func" fieldType="LRoot" ref="params" value="func" />
<putfield class="LRoot" field="input_signature" fieldType="LRoot" ref="params" value="input_signature" />
Expand All @@ -291,6 +297,22 @@
<return value="params" />
</method>
</class>
<class name="Do_not_convert" allocatable="true">
<method name="do" descriptor="()LRoot;" numArgs="2" paramNames="self test">
<putfield class="LRoot" field="params" fieldType="LRoot" ref="test" value="self" />
<return value="test" />
</method>
</class>
<class name="do_not_convert" allocatable="true">
<!-- https://www.tensorflow.org/versions/r2.9/api_docs/python/tf/autograph/experimental/do_not_convert -->
<method name="do" descriptor="()LRoot;" numArgs="4" paramNames="self params values extra">
<new def="closure" class="Ltensorflow/class/Do_not_convert" />
<putfield class="LRoot" field="test" fieldType="LRoot" ref="closure" value="self" />
<putfield class="LRoot" field="params" fieldType="LRoot" ref="closure" value="params" />
<putfield class="LRoot" field="values" fieldType="LRoot" ref="closure" value="values" />
<return value="closure" />
</method>
</class>
</package>
<package name="tensorflow/objects">
<class name="feature" allocatable="true" />
Expand Down
14 changes: 14 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_abstract_method3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# From https://blog.teclado.com/python-abc-abstract-base-classes/#introducing-abstract-classes.
import tensorflow as tf
from abc import ABC, abstractmethod


class C(ABC):

@abstractmethod
def f(self, x):
assert isinstance(x, tf.Tensor)


c = C()
c.f(tf.constant(1))
41 changes: 41 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_functions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import tensorflow
import pytest
import sys


@tensorflow.autograph.experimental.do_not_convert
def dummy_fun(a):
pass


@pytest.mark.parametrize("test_input,expected", [("3+5", 8), ("2+4", 6), ("6*9", 42)])
def dummy_test(x, test_input, expected):
pass


@pytest.mark.skipif(sys.version_info < (3, 10), reason="requires python3.10 or higher")
def test_function(x):
pass


@pytest.mark.skip(reason="requires python3.10 or higher")
def test_function2(x):
pass


@pytest.mark.skip("requires python3.10 or higher")
def test_function3(x):
pass


@pytest.mark.skip
def test_function4(x):
pass


dummy_fun(tensorflow.constant(1))
dummy_test(tensorflow.constant(1), "1", "1")
test_function(tensorflow.constant(1))
test_function2(tensorflow.constant(1))
test_function3(tensorflow.constant(1))
test_function4(tensorflow.constant(1))
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import tensorflow as tf


def f(x):
assert isinstance(x, tf.Tensor)


f(tf.constant(1))
13 changes: 13 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method10.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import tensorflow as tf


def mama(my_func):
return my_func


@mama
def f(x):
assert isinstance(x, tf.Tensor)


f(tf.constant(1))
10 changes: 10 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method11.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import tensorflow as tf
import pytest


@pytest.mark.skip
def f(a):
assert isinstance(a, tf.Tensor)


f(tf.constant(1))
27 changes: 27 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method12.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Test https://github.com/wala/ML/issues/188.

import tensorflow as tf


def mama(test=None):
assert test == "Hello"

def _mama(func):

def core(*args, **kwargs):
assert isinstance(args[0], tf.Tensor)
return func(*args, **kwargs)

return core

return _mama


@mama(test="Hello")
def f(x):
assert isinstance(x, tf.Tensor)
return 5


res = f(tf.constant(1))
assert res == 5
13 changes: 13 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method13.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import tensorflow as tf


def mama(my_func=None):
return my_func


@mama
def f(x):
assert isinstance(x, tf.Tensor)


f(tf.constant(1))
20 changes: 20 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Test for https://github.com/wala/ML/issues/188.

import tensorflow as tf


def mama(fun):

def wrapper_fun(*args, **kwargs):
assert isinstance(args[0], tf.Tensor)
fun(*args, **kwargs)

return wrapper_fun


@mama
def f(x):
assert isinstance(x, tf.Tensor)


f(tf.constant(1))
13 changes: 13 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method3.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import tensorflow as tf


def mama(fun):
return fun


@mama
def raffi(x):
assert isinstance(x, tf.Tensor)


raffi(tf.constant(1))
12 changes: 12 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method4.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import tensorflow as tf


def mama(fun):
return fun


def raffi(x):
assert isinstance(x, tf.Tensor)


raffi(tf.constant(1))
12 changes: 12 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method5.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import tensorflow as tf


def mama(fun):
return fun


def raffi(x):
assert isinstance(x, tf.Tensor)


mama(raffi(tf.constant(1)))
17 changes: 17 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method6.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import tensorflow as tf


def mama(fun):

def wrapper_fun(*args, **kwargs):
assert isinstance(args[0], tf.Tensor)
fun(*args, **kwargs)

return wrapper_fun


def f(x):
assert isinstance(x, tf.Tensor)


f(tf.constant(1))
17 changes: 17 additions & 0 deletions com.ibm.wala.cast.python.test/data/tf2_test_decorated_method7.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import tensorflow as tf


def mama(fun):

def wrapper_fun(*args, **kwargs):
assert isinstance(args[0], tf.Tensor)
fun(*args, **kwargs)

return wrapper_fun


def f(x):
assert isinstance(x, tf.Tensor)


mama(f(tf.constant(1)))
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import tensorflow as tf


def f(x):
assert isinstance(x, tf.Tensor)


f(tf.constant(1))
Loading

0 comments on commit 60955d6

Please sign in to comment.