blob: 7fe9b618d6e80d4b52d9ae5280c9896a76ad2c88 [file] [log] [blame]
Dean Moldovana9a37b42016-08-13 00:57:24 +02001import pytest
Jason Rhinelander391c7542017-07-25 16:47:36 -04002from pybind11_tests import enums as m
Dean Moldovana9a37b42016-08-13 00:57:24 +02003
4
5def test_unscoped_enum():
Jason Rhinelander391c7542017-07-25 16:47:36 -04006 assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
7 assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
8 assert str(m.EOne) == "UnscopedEnum.EOne"
Boris Staletic289e5d92018-04-02 23:26:48 +02009
10 # name property
11 assert m.UnscopedEnum.EOne.name == "EOne"
12 assert m.UnscopedEnum.ETwo.name == "ETwo"
13 assert m.EOne.name == "EOne"
14 # name readonly
15 with pytest.raises(AttributeError):
16 m.UnscopedEnum.EOne.name = ""
17 # name returns a copy
18 foo = m.UnscopedEnum.EOne.name
19 foo = "bar"
20 assert m.UnscopedEnum.EOne.name == "EOne"
21
Matthieu Becaf936e12017-03-03 08:45:50 -080022 # __members__ property
Jason Rhinelander391c7542017-07-25 16:47:36 -040023 assert m.UnscopedEnum.__members__ == \
Sergei Izmailov09f08292019-09-19 19:23:27 +030024 {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree}
Matthieu Becaf936e12017-03-03 08:45:50 -080025 # __members__ readonly
26 with pytest.raises(AttributeError):
Jason Rhinelander391c7542017-07-25 16:47:36 -040027 m.UnscopedEnum.__members__ = {}
Matthieu Becaf936e12017-03-03 08:45:50 -080028 # __members__ returns a copy
Jason Rhinelander391c7542017-07-25 16:47:36 -040029 foo = m.UnscopedEnum.__members__
Matthieu Becaf936e12017-03-03 08:45:50 -080030 foo["bar"] = "baz"
Jason Rhinelander391c7542017-07-25 16:47:36 -040031 assert m.UnscopedEnum.__members__ == \
Sergei Izmailov09f08292019-09-19 19:23:27 +030032 {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree}
Dean Moldovana9a37b42016-08-13 00:57:24 +020033
Sergei Izmailov09f08292019-09-19 19:23:27 +030034 for docstring_line in '''An unscoped enumeration
Wenzel Jakob6d190362017-11-16 22:24:36 +010035
36Members:
37
38 EOne : Docstring for EOne
39
Wenzel Jakob6d190362017-11-16 22:24:36 +010040 ETwo : Docstring for ETwo
41
Sergei Izmailov09f08292019-09-19 19:23:27 +030042 EThree : Docstring for EThree'''.split('\n'):
43 assert docstring_line in m.UnscopedEnum.__doc__
Wenzel Jakob6d190362017-11-16 22:24:36 +010044
Tarcísio Fischer54eb8192018-10-24 06:18:58 -030045 # Unscoped enums will accept ==/!= int comparisons
Jason Rhinelander391c7542017-07-25 16:47:36 -040046 y = m.UnscopedEnum.ETwo
Dean Moldovana9a37b42016-08-13 00:57:24 +020047 assert y == 2
Tarcísio Fischer54eb8192018-10-24 06:18:58 -030048 assert 2 == y
Dean Moldovana9a37b42016-08-13 00:57:24 +020049 assert y != 3
Tarcísio Fischer54eb8192018-10-24 06:18:58 -030050 assert 3 != y
Sergei Izmailov09f08292019-09-19 19:23:27 +030051 # Compare with None
52 assert (y != None) # noqa: E711
53 assert not (y == None) # noqa: E711
54 # Compare with an object
55 assert (y != object())
56 assert not (y == object())
57 # Compare with string
58 assert y != "2"
59 assert "2" != y
60 assert not ("2" == y)
61 assert not (y == "2")
62
63 with pytest.raises(TypeError):
64 y < object()
65
66 with pytest.raises(TypeError):
67 y <= object()
68
69 with pytest.raises(TypeError):
70 y > object()
71
72 with pytest.raises(TypeError):
73 y >= object()
74
75 with pytest.raises(TypeError):
76 y | object()
77
78 with pytest.raises(TypeError):
79 y & object()
80
81 with pytest.raises(TypeError):
82 y ^ object()
Dean Moldovana9a37b42016-08-13 00:57:24 +020083
Jason Rhinelander391c7542017-07-25 16:47:36 -040084 assert int(m.UnscopedEnum.ETwo) == 2
85 assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
Dean Moldovana9a37b42016-08-13 00:57:24 +020086
Pim Schellart90d27802016-11-16 11:28:11 -050087 # order
Jason Rhinelander391c7542017-07-25 16:47:36 -040088 assert m.UnscopedEnum.EOne < m.UnscopedEnum.ETwo
89 assert m.UnscopedEnum.EOne < 2
90 assert m.UnscopedEnum.ETwo > m.UnscopedEnum.EOne
91 assert m.UnscopedEnum.ETwo > 1
92 assert m.UnscopedEnum.ETwo <= 2
93 assert m.UnscopedEnum.ETwo >= 2
94 assert m.UnscopedEnum.EOne <= m.UnscopedEnum.ETwo
95 assert m.UnscopedEnum.EOne <= 2
96 assert m.UnscopedEnum.ETwo >= m.UnscopedEnum.EOne
97 assert m.UnscopedEnum.ETwo >= 1
98 assert not (m.UnscopedEnum.ETwo < m.UnscopedEnum.EOne)
99 assert not (2 < m.UnscopedEnum.EOne)
Pim Schellart90d27802016-11-16 11:28:11 -0500100
Sergei Izmailov09f08292019-09-19 19:23:27 +0300101 # arithmetic
102 assert m.UnscopedEnum.EOne & m.UnscopedEnum.EThree == m.UnscopedEnum.EOne
103 assert m.UnscopedEnum.EOne | m.UnscopedEnum.ETwo == m.UnscopedEnum.EThree
104 assert m.UnscopedEnum.EOne ^ m.UnscopedEnum.EThree == m.UnscopedEnum.ETwo
105
Dean Moldovana9a37b42016-08-13 00:57:24 +0200106
107def test_scoped_enum():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400108 assert m.test_scoped_enum(m.ScopedEnum.Three) == "ScopedEnum::Three"
109 z = m.ScopedEnum.Two
110 assert m.test_scoped_enum(z) == "ScopedEnum::Two"
Dean Moldovana9a37b42016-08-13 00:57:24 +0200111
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300112 # Scoped enums will *NOT* accept ==/!= int comparisons (Will always return False)
113 assert not z == 3
114 assert not 3 == z
115 assert z != 3
116 assert 3 != z
Sergei Izmailov09f08292019-09-19 19:23:27 +0300117 # Compare with None
118 assert (z != None) # noqa: E711
119 assert not (z == None) # noqa: E711
120 # Compare with an object
121 assert (z != object())
122 assert not (z == object())
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300123 # Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions)
Dean Moldovana9a37b42016-08-13 00:57:24 +0200124 with pytest.raises(TypeError):
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300125 z > 3
Dean Moldovana9a37b42016-08-13 00:57:24 +0200126 with pytest.raises(TypeError):
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300127 z < 3
128 with pytest.raises(TypeError):
129 z >= 3
130 with pytest.raises(TypeError):
131 z <= 3
Dean Moldovana9a37b42016-08-13 00:57:24 +0200132
Pim Schellart90d27802016-11-16 11:28:11 -0500133 # order
Jason Rhinelander391c7542017-07-25 16:47:36 -0400134 assert m.ScopedEnum.Two < m.ScopedEnum.Three
135 assert m.ScopedEnum.Three > m.ScopedEnum.Two
136 assert m.ScopedEnum.Two <= m.ScopedEnum.Three
137 assert m.ScopedEnum.Two <= m.ScopedEnum.Two
138 assert m.ScopedEnum.Two >= m.ScopedEnum.Two
139 assert m.ScopedEnum.Three >= m.ScopedEnum.Two
Dean Moldovana9a37b42016-08-13 00:57:24 +0200140
Dean Moldovanbad17402016-11-20 21:21:54 +0100141
Dean Moldovana9a37b42016-08-13 00:57:24 +0200142def test_implicit_conversion():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400143 assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
144 assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
Dean Moldovana9a37b42016-08-13 00:57:24 +0200145
Jason Rhinelander391c7542017-07-25 16:47:36 -0400146 f = m.ClassWithUnscopedEnum.test_function
147 first = m.ClassWithUnscopedEnum.EFirstMode
148 second = m.ClassWithUnscopedEnum.ESecondMode
Dean Moldovana9a37b42016-08-13 00:57:24 +0200149
150 assert f(first) == 1
151
152 assert f(first) == f(first)
153 assert not f(first) != f(first)
154
155 assert f(first) != f(second)
156 assert not f(first) == f(second)
157
158 assert f(first) == int(f(first))
159 assert not f(first) != int(f(first))
160
161 assert f(first) != int(f(second))
162 assert not f(first) == int(f(second))
163
164 # noinspection PyDictCreation
165 x = {f(first): 1, f(second): 2}
166 x[f(first)] = 3
167 x[f(second)] = 4
168 # Hashing test
169 assert str(x) == "{EMode.EFirstMode: 3, EMode.ESecondMode: 4}"
Pim Schellart90d27802016-11-16 11:28:11 -0500170
Dean Moldovanbad17402016-11-20 21:21:54 +0100171
Pim Schellart90d27802016-11-16 11:28:11 -0500172def test_binary_operators():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400173 assert int(m.Flags.Read) == 4
174 assert int(m.Flags.Write) == 2
175 assert int(m.Flags.Execute) == 1
176 assert int(m.Flags.Read | m.Flags.Write | m.Flags.Execute) == 7
177 assert int(m.Flags.Read | m.Flags.Write) == 6
178 assert int(m.Flags.Read | m.Flags.Execute) == 5
179 assert int(m.Flags.Write | m.Flags.Execute) == 3
180 assert int(m.Flags.Write | 1) == 3
Lori A. Burnsf6c4c102019-09-04 16:16:21 -0400181 assert ~m.Flags.Write == -3
Pim Schellart90d27802016-11-16 11:28:11 -0500182
Jason Rhinelander391c7542017-07-25 16:47:36 -0400183 state = m.Flags.Read | m.Flags.Write
184 assert (state & m.Flags.Read) != 0
185 assert (state & m.Flags.Write) != 0
186 assert (state & m.Flags.Execute) == 0
Pim Schellart90d27802016-11-16 11:28:11 -0500187 assert (state & 1) == 0
188
189 state2 = ~state
190 assert state2 == -7
191 assert int(state ^ state2) == -1
Wenzel Jakobe6fd2cd2017-04-28 14:46:52 +0200192
Wenzel Jakob7653a112017-04-28 22:43:14 +0200193
Wenzel Jakobe6fd2cd2017-04-28 14:46:52 +0200194def test_enum_to_int():
Wenzel Jakob31680e62019-09-20 11:06:10 +0200195 m.test_enum_to_int(m.Flags.Read)
196 m.test_enum_to_int(m.ClassWithUnscopedEnum.EMode.EFirstMode)
197 m.test_enum_to_uint(m.Flags.Read)
198 m.test_enum_to_uint(m.ClassWithUnscopedEnum.EMode.EFirstMode)
199 m.test_enum_to_long_long(m.Flags.Read)
200 m.test_enum_to_long_long(m.ClassWithUnscopedEnum.EMode.EFirstMode)
Krzysztof Fornalczyk5c8746f2018-09-11 10:59:56 +0200201
202
203def test_duplicate_enum_name():
204 with pytest.raises(ValueError) as excinfo:
205 m.register_bad_enum()
Wenzel Jakobf4245182018-09-01 01:20:24 +0200206 assert str(excinfo.value) == 'SimpleEnum: element "ONE" already exists!'