Skip to content

Commit

Permalink
move validate_bindings_compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
pthom committed Nov 15, 2024
1 parent 13a0147 commit 7447a06
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 68 deletions.
58 changes: 1 addition & 57 deletions src/litgen/integration_tests/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,69 +98,13 @@ Integration tests (litgen/src/litgen/integration_tests) will compile the binding

### Develop and debug integration tests

The file "src/litgen/tests/internal/test_validate_bindings_compilation.py" is a sandbox where you can:
The script "src/litgen/validate_bindings_compilation/validate_bindings_compilation.py" contains a sandbox where you can:
- provide C++ sample code for which to generate bindings
- provide options for litgen
- provide python sample code that will test the generated bindings

This is a good place to develop and debug litgen, before running the full integration tests.

**Example content:**
In this example, we provide a simple C++ struct where a C float array should be bound as a numpy array in Python,
and a python test that will check that the bindings work as expected.

The bindings are tested for both pybind11 and nanobind.

```python
import litgen
from litgen.internal.validate_bindings_compilation import validate_bindings_compilation


def test_validate_bindings_compilation() -> None:
# Validates that the cpp code can be compiled into bindings and
# that the generated Python bindings work as expected.
# **This kind of test is slow**, do not use it extensively in CI.


code = """
#include <cstddef>
#include <cstdint>
struct Color4
{
Color4(const uint8_t _rgba[4])
{
for (size_t i = 0; i < 4; ++i)
rgba[i] = _rgba[i];
}
uint8_t rgba[4] = {0, 0, 0, 0};
};
"""
python_test_code = """
import validate_bindings_compilation
import numpy as np
def test_validate_bindings_compilation() -> None:
c = validate_bindings_compilation.Color4([1, 2, 3, 4])
assert c.rgba[2] == 3
"""

for bind_type in litgen.BindLibraryType:
# for bind_type in [litgen.BindLibraryType.nanobind]:
options = litgen.LitgenOptions()
options.bind_library = bind_type

success = validate_bindings_compilation(
cpp_code=code,
options=options,
remove_build_dir_on_success=False,
python_test_code=python_test_code,
show_logs=True,
python_module_name="validate_bindings_compilation",
# work_dir="/Users/pascal/dvp/OpenSource/ImGuiWork/_Bundle/litgen/src/litgen/tests/internal/ppp"
)
assert success
```

### Run the full integration tests

Expand Down
70 changes: 70 additions & 0 deletions src/litgen/validate_bindings_compilation/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
The script "src/litgen/validate_bindings_compilation/validate_bindings_compilation.py" contains a sandbox where you can:
- provide C++ sample code for which to generate bindings
- provide options for litgen
- provide python sample code that will test the generated bindings


It is used mainly for litgen development and testing.

Edit the file `run_validate_bindings_compilation.py` to specify some C++ and Python test code, which you want to validate.


**Example content:**
In this example, we provide a simple C++ struct where a C float array should be bound as a numpy array in Python,
and a python test that will check that the bindings work as expected.

The bindings are tested for both pybind11 and nanobind.

```python
import litgen
from litgen.validate_bindings_compilation.validate_bindings_compilation import validate_bindings_compilation


def main() -> None:
# Validates that the cpp code can be compiled into bindings and
# that the generated Python bindings work as expected.
# **This kind of test is slow**, do not use it extensively in CI.
# return
code = """
#include <vector>
std::vector<int> range(int i) {
std::vector<int> v;
for (int j = 0; j < i; j++) {
v.push_back(j);
}
return v;
}
"""
python_test_code = """
import validate_bindings_compilation
def test_validate_bindings_compilation() -> None:
c = validate_bindings_compilation.range(5)
assert c == [0, 1, 2, 3, 4]
"""

# for bind_type in litgen.BindLibraryType:
for bind_type in [litgen.BindLibraryType.nanobind]:
options = litgen.LitgenOptions()
options.fn_params_replace_buffer_by_array__regex = r".*"
options.bind_library = bind_type
options.fn_params_adapt_mutable_param_with_default_value__regex = r".*"

success = validate_bindings_compilation(
cpp_code=code,
options=options,
remove_build_dir_on_success=False,
python_test_code=python_test_code,
show_logs=True,
python_module_name="validate_bindings_compilation",
# work_dir="/Users/pascal/dvp/OpenSource/ImGuiWork/_Bundle/litgen/src/litgen/tests/internal/ppp",
# enable_hack_code=True,
)
assert success


if __name__ == "__main__":
main()
```
Empty file.
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
import litgen
from litgen.internal.validate_bindings_compilation import validate_bindings_compilation
from litgen.validate_bindings_compilation.validate_bindings_compilation import validate_bindings_compilation


def test_validate_bindings_compilation() -> None:
def main() -> None:
# Validates that the cpp code can be compiled into bindings and
# that the generated Python bindings work as expected.
# **This kind of test is slow**, do not use it extensively in CI.
# return
code = """
#include <vector>
#include <map>
#include <string>
struct FooBrace {
std::vector<int> int_values = {1, 2, 3};
std::map<std::string, int> dict_string_int{{"abc", 3}};
};
std::vector<int> range(int i) {
std::vector<int> v;
for (int j = 0; j < i; j++) {
v.push_back(j);
}
return v;
}
"""
python_test_code = """
import validate_bindings_compilation
def test_validate_bindings_compilation() -> None:
c = validate_bindings_compilation.FooBrace()
c = validate_bindings_compilation.range(5)
assert c == [0, 1, 2, 3, 4]
"""

# for bind_type in litgen.BindLibraryType:
Expand All @@ -42,3 +45,7 @@ def test_validate_bindings_compilation() -> None:
# enable_hack_code=True,
)
assert success


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,18 @@ def validate_bindings_compilation(
#include <vector>
#include <tuple>
#include <nanobind/nanobind.h>
#include <nanobind/stl/string.h>
#include <nanobind/trampoline.h>
#include <nanobind/stl/array.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
#include <nanobind/stl/optional.h>
#include <nanobind/stl/function.h>
#include <nanobind/stl/shared_ptr.h>
#include <nanobind/stl/unique_ptr.h>
#include <nanobind/stl/map.h>
#include <nanobind/stl/tuple.h>
#include <nanobind/make_iterator.h>
#include <nanobind/ndarray.h>
#include <nanobind/trampoline.h>
#include <nanobind/ndarray.h>
Expand Down Expand Up @@ -237,7 +246,7 @@ def validate_bindings_compilation(
# The module was built in the work_dir, it can be imported directly (no need to move it)
if python_test_code:
# Write test code to a test file
test_file_name = "test_validate_bindings_compilation.py"
test_file_name = "run_validate_bindings_compilation.py"
test_file_path = os.path.join(work_dir, test_file_name)
with open(test_file_path, "w") as f:
f.write(code_utils.unindent_code(python_test_code))
Expand Down

0 comments on commit 7447a06

Please sign in to comment.