Skip to content

Commit

Permalink
test(frontend-python): enable coverage back
Browse files Browse the repository at this point in the history
  • Loading branch information
umut-sahin committed Sep 9, 2024
1 parent f19f071 commit edaa208
Show file tree
Hide file tree
Showing 13 changed files with 76 additions and 44 deletions.
14 changes: 9 additions & 5 deletions frontends/concrete-python/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@ BINDINGS_DIRECTORY=${COMPILER_BUILD_DIRECTORY}/tools/concretelang/python_package
TFHERS_UTILS_DIRECTORY ?= $(PWD)/tests/tfhers-utils/

OS=undefined
COVERAGE_OPT=""
ifeq ($(shell uname), Linux)
OS=linux
COVERAGE_OPT="--cov=concrete.fhe --cov-fail-under=100 --cov-report=term-missing:skip-covered"
RUNTIME_LIBRARY?=${COMPILER_BUILD_DIRECTORY}/lib/libConcretelangRuntime.so
else ifeq ($(shell uname), Darwin)
OS=darwin
Expand Down Expand Up @@ -72,7 +70,9 @@ pytest: pytest-default
pytest-default: tfhers-utils
eval $(shell make silent_cp_activate)
pytest tests -svv -n auto \
${COVERAGE_OPT} \
--cov=concrete.fhe \
--cov-fail-under=100 \
--cov-report=term-missing:skip-covered \
--key-cache "${KEY_CACHE_DIRECTORY}" \
-m "${PYTEST_MARKERS}"

Expand All @@ -96,7 +96,9 @@ pytest-multi: tfhers-utils
pytest tests -svv -n auto \
--precision=multi \
--strategy=multi \
${COVERAGE_OPT} \
--cov=concrete.fhe \
--cov-fail-under=100 \
--cov-report=term-missing:skip-covered \
--key-cache "${KEY_CACHE_DIRECTORY}" \
-m "${PYTEST_MARKERS}"

Expand All @@ -110,7 +112,9 @@ pytest-gpu: tfhers-utils
# test multi precision
pytest tests -svv -n0 --use_gpu \
--precision=multi \
${COVERAGE_OPT} \
--cov=concrete.fhe \
--cov-fail-under=100 \
--cov-report=term-missing:skip-covered \
--key-cache "${KEY_CACHE_DIRECTORY}" \
-m "${PYTEST_MARKERS}"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from ..representation import Graph

if TYPE_CHECKING:
if TYPE_CHECKING: # pragma: no cover
from .module import ExecutionRt
from .utils import Lazy

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ def __str__(self):
return self.graph.format()

def __repr__(self) -> str:
return f"FheFunction({self.name=})"
return f"FheFunction(name={self.name})"

def simulate(self, *args: Any) -> Any:
"""
Expand Down
36 changes: 14 additions & 22 deletions frontends/concrete-python/concrete/fhe/mlir/converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -538,17 +538,13 @@ def matmul(self, ctx: Context, node: Node, preds: List[Conversion]) -> Conversio

def max(self, ctx: Context, node: Node, preds: List[Conversion]) -> Conversion:
assert len(preds) == 1

if all(pred.is_encrypted for pred in preds):
return ctx.min_max(
ctx.typeof(node),
preds[0],
axes=node.properties["kwargs"].get("axis", ()),
keep_dims=node.properties["kwargs"].get("keepdims", False),
operation="max",
)

return self.tlu(ctx, node, preds)
return ctx.min_max(
ctx.typeof(node),
preds[0],
axes=node.properties["kwargs"].get("axis", ()),
keep_dims=node.properties["kwargs"].get("keepdims", False),
operation="max",
)

def maximum(self, ctx: Context, node: Node, preds: List[Conversion]) -> Conversion:
assert len(preds) == 2
Expand Down Expand Up @@ -578,17 +574,13 @@ def maxpool3d(self, ctx: Context, node: Node, preds: List[Conversion]) -> Conver

def min(self, ctx: Context, node: Node, preds: List[Conversion]) -> Conversion:
assert len(preds) == 1

if all(pred.is_encrypted for pred in preds):
return ctx.min_max(
ctx.typeof(node),
preds[0],
axes=node.properties["kwargs"].get("axis", ()),
keep_dims=node.properties["kwargs"].get("keepdims", False),
operation="min",
)

return self.tlu(ctx, node, preds)
return ctx.min_max(
ctx.typeof(node),
preds[0],
axes=node.properties["kwargs"].get("axis", ()),
keep_dims=node.properties["kwargs"].get("keepdims", False),
operation="min",
)

def minimum(self, ctx: Context, node: Node, preds: List[Conversion]) -> Conversion:
assert len(preds) == 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def __init__(self, index: Tuple[int, ...]):

# get the representation of the mock
def __repr__(self) -> str:
return f"{self.indices}"
return f"{self.indices}" # pragma: no cover

# combine the indices of the mock with another mock into a new mock
def combine(self, other: "Mock") -> "Mock":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -357,9 +357,6 @@ def minimum_maximum(self, node: Node, preds: List[Node]):
x = preds[0]
y = preds[1]

assert x.output.is_encrypted
assert y.output.is_encrypted

assert isinstance(x.output.dtype, Integer)
assert isinstance(y.output.dtype, Integer)
assert isinstance(node.output.dtype, Integer)
Expand Down
3 changes: 3 additions & 0 deletions frontends/concrete-python/concrete/fhe/representation/node.py
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,9 @@ def format(self, predecessors: List[str], maximum_constant_length: int = 45) ->
if name not in KWARGS_IGNORED_IN_FORMATTING
)

if name in {"amin", "amax"}:
name = name[1:]

return f"{name}({', '.join(args)})"

def label(self) -> str:
Expand Down
12 changes: 6 additions & 6 deletions frontends/concrete-python/concrete/fhe/tfhers/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def _input_type(self, input_idx: int) -> Optional[TFHERSIntegerType]:
Optional[TFHERSIntegerType]: input type. None means a non-tfhers type
"""
if isinstance(self.input_types, list):
return self.input_types[input_idx]
return self.input_types[input_idx] # pragma: no cover
return self.input_types

def _output_type(self, output_idx: int) -> Optional[TFHERSIntegerType]:
Expand All @@ -54,7 +54,7 @@ def _output_type(self, output_idx: int) -> Optional[TFHERSIntegerType]:
Optional[TFHERSIntegerType]: output type. None means a non-tfhers type
"""
if isinstance(self.output_types, list):
return self.output_types[output_idx]
return self.output_types[output_idx] # pragma: no cover
return self.output_types

def _input_keyid(self, input_idx: int) -> int:
Expand Down Expand Up @@ -125,11 +125,11 @@ def import_value(self, buffer: bytes, input_idx: int) -> "fhe.Value":
TfhersExporter.import_fheuint8(buffer, fheint_desc, keyid, variance)
)

msg = (
msg = ( # pragma: no cover
f"importing {'signed' if signed else 'unsigned'} integers of {bit_width}bits is not"
" yet supported"
)
raise NotImplementedError(msg)
raise NotImplementedError(msg) # pragma: no cover

def export_value(self, value: "fhe.Value", output_idx: int) -> bytes:
"""Export a value as a serialized TFHErs integer.
Expand All @@ -154,11 +154,11 @@ def export_value(self, value: "fhe.Value", output_idx: int) -> bytes:
if not signed:
return TfhersExporter.export_fheuint8(value.inner, fheint_desc)

msg = (
msg = ( # pragma: no cover
f"exporting value to {'signed' if signed else 'unsigned'} integers of {bit_width}bits"
" is not yet supported"
)
raise NotImplementedError(msg)
raise NotImplementedError(msg) # pragma: no cover

def serialize_input_secret_key(self, input_idx: int) -> bytes:
"""Serialize secret key used for a specific input.
Expand Down
2 changes: 1 addition & 1 deletion frontends/concrete-python/concrete/fhe/tfhers/values.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def __init__(
except Exception as e: # pylint: disable=broad-except
msg = f"got error while trying to convert list value into a numpy array: {e}"
raise ValueError(msg) from e
if value.dtype == np.dtype("O"):
if value.dtype == np.dtype("O"): # pragma: no cover
msg = "malformed value array"
raise ValueError(msg)

Expand Down
5 changes: 5 additions & 0 deletions frontends/concrete-python/tests/compilation/test_modules.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,9 @@ def dec(x):
module.cleanup()
assert set(artifacts.functions.keys()) == {"inc", "dec"}

assert repr(module.inc) == "FheFunction(name=inc)"
assert repr(module.dec) == "FheFunction(name=dec)"


def test_compiled_wrong_attribute():
"""
Expand Down Expand Up @@ -331,6 +334,8 @@ def dec(x):
assert module.inc.simulate(5) == 6
assert module.dec.simulate(5) == 4

module.cleanup()


@pytest.mark.graphviz
def test_print(helpers):
Expand Down
14 changes: 10 additions & 4 deletions frontends/concrete-python/tests/execution/test_min_max.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from concrete.fhe.values import ValueDescription

cases = []
for operation in [("max", lambda x: np.max(x)), ("min", lambda x: np.min(x))]:
for operation in ["max", "min"]:
for bit_width in range(1, 5):
for is_signed in [False, True]:
for shape in [(), (4,), (3, 3)]:
Expand Down Expand Up @@ -135,20 +135,26 @@ def test_min_max(
Test np.min/np.max on encrypted values.
"""

name, function = operation

dtype = Integer(is_signed=is_signed, bit_width=bit_width)
description = ValueDescription(dtype, shape=shape, is_encrypted=True)

print()
print()
print(
f"np.{name}({description}, axis={axis}, keepdims={keepdims})"
f"np.{operation}({description}, axis={axis}, keepdims={keepdims})"
+ (f" {{{strategy}}}" if strategy is not None else "")
)
print()
print()

assert operation in {"min", "max"}

def function(x):
if operation == "min":
return np.min(x, axis=axis, keepdims=keepdims)
else:
return np.max(x, axis=axis, keepdims=keepdims)

parameter_encryption_statuses = {"x": "encrypted"}
configuration = helpers.configuration()

Expand Down
8 changes: 8 additions & 0 deletions frontends/concrete-python/tests/execution/test_others.py
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,14 @@ def issue650(x):
{},
id="(x ** 3, x + 100)",
),
pytest.param(
lambda x: np.min(x, 0),
{
"x": {"range": [0, 10], "status": "encrypted", "shape": (2, 2)},
},
{},
id="np.min(x, 0)",
),
],
)
def test_others(function, parameters, configuration_overrides, helpers):
Expand Down
17 changes: 17 additions & 0 deletions frontends/concrete-python/tests/mlir/test_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,23 @@ def assign(x, y):
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ but it needs to be for where operation
return %3
""", # noqa: E501
),
pytest.param(
lambda x: np.min(x),
{"x": "clear"},
fhe.inputset(fhe.tensor[fhe.uint3, 3, 2]), # type: ignore
RuntimeError,
"""
Function you are trying to compile cannot be compiled
%0 = x # ClearTensor<uint3, shape=(3, 2)> ∈ [0, 7]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ value is clear
%1 = min(%0) # ClearScalar<uint3> ∈ [0, 4]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ but computing min of clear values is not supported
return %1
""", # noqa: E501
),
],
Expand Down

0 comments on commit edaa208

Please sign in to comment.