Skip to content

Commit

Permalink
Merge pull request #138 from robotpy/more-tests
Browse files Browse the repository at this point in the history
More tests
  • Loading branch information
virtuald authored Jan 5, 2022
2 parents 0fe238b + 20d8275 commit f58ab1b
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 9 deletions.
14 changes: 6 additions & 8 deletions robotpy_build/templates/pybind11.cpp.j2
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,16 @@
{%- macro genprop(qualname, prop) -%}
{%- if prop.array_size is defined -%}
.def_property_readonly("{{ prop.x_name }}", []({{ qualname }}& inst) {
return py::memoryview(py::buffer_info(
return py::memoryview::from_buffer(
&inst.{{ prop.name }}, sizeof({{ prop.type }}),
py::format_descriptor<{{ prop.type }}>::format(),
1, {{ "{" }}{{ prop.array_size }}{{ "}" }}, {sizeof({{ prop.type }})}
));
py::format_descriptor<{{ prop.type }}>::value,
{{ "{" }}{{ prop.array_size }}{{ "}" }}, {sizeof({{ prop.type }})},
{% if prop.x_readonly %}true{% else %}false{% endif %}
);
}
{{- doc(prop, ', py::doc(', ')') }})
{%- elif prop.array -%}
.def_property("{{ prop.x_name }}",
[](const {{ qualname }}& inst) { return inst.{{ prop.name}}; },
[]({{ qualname }}& inst, const {{ prop.type }} v) {inst.{{ prop.name}} = v; }
{{- doc(prop, ', py::doc(', ')') }})
{# cannot sensibly autowrap an array of incomplete size #}
{%- elif prop.reference -%}
.def_property
{%- if prop.constant or prop.constexpr or prop.x_readonly -%}
Expand Down
5 changes: 5 additions & 0 deletions tests/cpp/gen/ft/enums.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

enums:
StripPrefixEnum:
value_prefix: STRIP_
2 changes: 2 additions & 0 deletions tests/cpp/pyproject.toml.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ generate = [
name = "rpytest_ft"

sources = [
"rpytest/ft/src/fields.cpp",
"rpytest/ft/src/ft.cpp"
]

Expand All @@ -40,6 +41,7 @@ generate = [
{ docstrings = "docstrings.h" },
{ docstrings_append = "docstrings_append.h" },
{ enums = "enums.h" },
{ fields = "fields.h" },
{ keepalive = "keepalive.h" },
{ ignore = "ignore.h" },
{ lifetime = "lifetime.h" },
Expand Down
4 changes: 4 additions & 0 deletions tests/cpp/rpytest/ft/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# autogenerated by 'robotpy-build create-imports rpytest.ft rpytest.ft._rpytest_ft'
from ._rpytest_ft import (
Abstract,
ClassWithFields,
ClassWithIgnored,
ClassWithTrampoline,
DocAppendClass,
Expand Down Expand Up @@ -35,6 +36,7 @@
RenamedClass,
RenamedEnum,
StaticOnly,
StripPrefixEnum,
TBase,
TBaseGetN4,
TBaseGetN6,
Expand Down Expand Up @@ -71,6 +73,7 @@

__all__ = [
"Abstract",
"ClassWithFields",
"ClassWithIgnored",
"ClassWithTrampoline",
"DocAppendClass",
Expand Down Expand Up @@ -103,6 +106,7 @@
"RenamedClass",
"RenamedEnum",
"StaticOnly",
"StripPrefixEnum",
"TBase",
"TBaseGetN4",
"TBaseGetN6",
Expand Down
14 changes: 13 additions & 1 deletion tests/cpp/rpytest/ft/include/enums.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@

#pragma once

// note: unnamed enums not supported at this time
// unnamed enum at global scope not supported yet
// enum { UGEX = 7 };

// global enum
enum GEnum { GE1 = 1 };
Expand All @@ -11,15 +12,23 @@ enum class GCEnum { GCE1 = 1 };

// global enum in a namespace
namespace enum_ns {

enum NSGEnum { NSGE2 = 2 };
enum class NSGCEnum { NSGE2 = 2 };

// unnamed enum in a namespace not supported yet
// enum { NSUGEX = 5 };

} // namespace enum_ns

// enum in a class
class EnumContainer {
public:
enum InnerEnum { IE1 = 1 };
enum class InnerCEnum { IEC1 = 1 };

// unnamed enum in a class
enum { UEX = 4 };
};

// enum in a namespace in a class
Expand All @@ -30,3 +39,6 @@ class NSEnumContainer {
enum class InnerCEnum { NSIEC1 = 1 };
};
}; // namespace enum_container_ns

// strip prefix
enum StripPrefixEnum { STRIP_1 = 1, STRIP_B = 2 };
39 changes: 39 additions & 0 deletions tests/cpp/rpytest/ft/include/fields.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <stdint.h>

class ClassWithFields {
public:
ClassWithFields() : ref_int(actual_int) {
array_of_two[0] = 0x10;
array_of_two[1] = 0x22;

ref_int = actual_int;
}

// array with size
int array_of_two[2];

int get_array_of_two(int index) { return array_of_two[index]; }

// readwrite
int actual_int = 2;

// reference
int &ref_int;

// constant
const int const_field = 3;

// static
static int static_int;

// constant static
const static int static_const = 5;

// constexpr
constexpr static int static_constexpr = 6;

// there's no sensible way to deal with this automatically
int should_be_ignored[];
};
5 changes: 5 additions & 0 deletions tests/cpp/rpytest/ft/src/fields.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@

#include <fields.h>

int ClassWithFields::static_int = 4;
const int ClassWithFields::static_const;
13 changes: 13 additions & 0 deletions tests/test_ft_enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,21 @@ def test_enums():
assert ft.EnumContainer.InnerEnum.IE1 == 1
assert ft.NSEnumContainer.InnerEnum.NSIE1 == 1

# Unnamed enums are hoisted as integers to their scope
# - not supported yet for globals
# assert ft._rpytest_ft.UGEX == 7
# assert ft._rpytest_ft.NSUGEX == 5
assert ft.EnumContainer.UEX == 4

# enum class are specific types
assert "GCE1" in ft.GCEnum.GCE1.__members__
assert "NSGE2" in ft.NSGCEnum.NSGE2.__members__
assert "IEC1" in ft.EnumContainer.InnerCEnum.__members__
assert "NSIEC1" in ft.NSEnumContainer.InnerCEnum.__members__


def test_enum_strip_prefix():
# 1 isn't a valid identifier, so it's not stripped
assert ft.StripPrefixEnum.STRIP_1 == 1
# STRIP_B is converted to B
assert ft.StripPrefixEnum.B == 2
36 changes: 36 additions & 0 deletions tests/test_ft_fields.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from rpytest.ft import ClassWithFields


def test_fields():

c = ClassWithFields()

assert "should_be_ignored" not in dir(c)
assert "array_of_two" in dir(c)

assert len(c.array_of_two) == 2
assert c.array_of_two[0] == 0x10
assert c.array_of_two[1] == 0x22

c.array_of_two[1] = 0x42
assert c.get_array_of_two(1) == 0x42

assert c.const_field == 3

assert ClassWithFields.static_int == 4
ClassWithFields.static_int = 44
assert ClassWithFields.static_int == 44

assert ClassWithFields.static_const == 5
assert ClassWithFields.static_constexpr == 6

assert c.actual_int == 2
assert c.ref_int == 2

c.actual_int = 3
assert c.ref_int == 3

# TODO: this probably has subtle issues, should always
# be readonly?
c.ref_int = 4
assert c.actual_int == 4

0 comments on commit f58ab1b

Please sign in to comment.