blob: 46cb379463defc70deb1d7d7251a3f905a62fc4c [file] [log] [blame]
Henry Schreinerd8c7ee02020-07-20 13:35:21 -04001# -*- coding: utf-8 -*-
Dean Moldovana9a37b42016-08-13 00:57:24 +02002import pytest
Jason Rhinelander391c7542017-07-25 16:47:36 -04003from pybind11_tests import enums as m
Dean Moldovana9a37b42016-08-13 00:57:24 +02004
5
6def test_unscoped_enum():
Jason Rhinelander391c7542017-07-25 16:47:36 -04007 assert str(m.UnscopedEnum.EOne) == "UnscopedEnum.EOne"
8 assert str(m.UnscopedEnum.ETwo) == "UnscopedEnum.ETwo"
9 assert str(m.EOne) == "UnscopedEnum.EOne"
David Vo5e6ec492020-09-20 09:12:19 +100010 assert repr(m.UnscopedEnum.EOne) == "<UnscopedEnum.EOne: 1>"
11 assert repr(m.UnscopedEnum.ETwo) == "<UnscopedEnum.ETwo: 2>"
12 assert repr(m.EOne) == "<UnscopedEnum.EOne: 1>"
Boris Staletic289e5d92018-04-02 23:26:48 +020013
14 # name property
15 assert m.UnscopedEnum.EOne.name == "EOne"
16 assert m.UnscopedEnum.ETwo.name == "ETwo"
17 assert m.EOne.name == "EOne"
18 # name readonly
19 with pytest.raises(AttributeError):
20 m.UnscopedEnum.EOne.name = ""
21 # name returns a copy
22 foo = m.UnscopedEnum.EOne.name
23 foo = "bar"
24 assert m.UnscopedEnum.EOne.name == "EOne"
25
Matthieu Becaf936e12017-03-03 08:45:50 -080026 # __members__ property
Jason Rhinelander391c7542017-07-25 16:47:36 -040027 assert m.UnscopedEnum.__members__ == \
Sergei Izmailov09f08292019-09-19 19:23:27 +030028 {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree}
Matthieu Becaf936e12017-03-03 08:45:50 -080029 # __members__ readonly
30 with pytest.raises(AttributeError):
Jason Rhinelander391c7542017-07-25 16:47:36 -040031 m.UnscopedEnum.__members__ = {}
Matthieu Becaf936e12017-03-03 08:45:50 -080032 # __members__ returns a copy
Jason Rhinelander391c7542017-07-25 16:47:36 -040033 foo = m.UnscopedEnum.__members__
Matthieu Becaf936e12017-03-03 08:45:50 -080034 foo["bar"] = "baz"
Jason Rhinelander391c7542017-07-25 16:47:36 -040035 assert m.UnscopedEnum.__members__ == \
Sergei Izmailov09f08292019-09-19 19:23:27 +030036 {"EOne": m.UnscopedEnum.EOne, "ETwo": m.UnscopedEnum.ETwo, "EThree": m.UnscopedEnum.EThree}
Dean Moldovana9a37b42016-08-13 00:57:24 +020037
Sergei Izmailov09f08292019-09-19 19:23:27 +030038 for docstring_line in '''An unscoped enumeration
Wenzel Jakob6d190362017-11-16 22:24:36 +010039
40Members:
41
42 EOne : Docstring for EOne
43
Wenzel Jakob6d190362017-11-16 22:24:36 +010044 ETwo : Docstring for ETwo
45
Sergei Izmailov09f08292019-09-19 19:23:27 +030046 EThree : Docstring for EThree'''.split('\n'):
47 assert docstring_line in m.UnscopedEnum.__doc__
Wenzel Jakob6d190362017-11-16 22:24:36 +010048
Tarcísio Fischer54eb8192018-10-24 06:18:58 -030049 # Unscoped enums will accept ==/!= int comparisons
Jason Rhinelander391c7542017-07-25 16:47:36 -040050 y = m.UnscopedEnum.ETwo
Dean Moldovana9a37b42016-08-13 00:57:24 +020051 assert y == 2
Tarcísio Fischer54eb8192018-10-24 06:18:58 -030052 assert 2 == y
Dean Moldovana9a37b42016-08-13 00:57:24 +020053 assert y != 3
Tarcísio Fischer54eb8192018-10-24 06:18:58 -030054 assert 3 != y
Sergei Izmailov09f08292019-09-19 19:23:27 +030055 # Compare with None
56 assert (y != None) # noqa: E711
57 assert not (y == None) # noqa: E711
58 # Compare with an object
59 assert (y != object())
60 assert not (y == object())
61 # Compare with string
62 assert y != "2"
63 assert "2" != y
64 assert not ("2" == y)
65 assert not (y == "2")
66
67 with pytest.raises(TypeError):
68 y < object()
69
70 with pytest.raises(TypeError):
71 y <= object()
72
73 with pytest.raises(TypeError):
74 y > object()
75
76 with pytest.raises(TypeError):
77 y >= object()
78
79 with pytest.raises(TypeError):
80 y | object()
81
82 with pytest.raises(TypeError):
83 y & object()
84
85 with pytest.raises(TypeError):
86 y ^ object()
Dean Moldovana9a37b42016-08-13 00:57:24 +020087
Jason Rhinelander391c7542017-07-25 16:47:36 -040088 assert int(m.UnscopedEnum.ETwo) == 2
89 assert str(m.UnscopedEnum(2)) == "UnscopedEnum.ETwo"
Dean Moldovana9a37b42016-08-13 00:57:24 +020090
Pim Schellart90d27802016-11-16 11:28:11 -050091 # order
Jason Rhinelander391c7542017-07-25 16:47:36 -040092 assert m.UnscopedEnum.EOne < m.UnscopedEnum.ETwo
93 assert m.UnscopedEnum.EOne < 2
94 assert m.UnscopedEnum.ETwo > m.UnscopedEnum.EOne
95 assert m.UnscopedEnum.ETwo > 1
96 assert m.UnscopedEnum.ETwo <= 2
97 assert m.UnscopedEnum.ETwo >= 2
98 assert m.UnscopedEnum.EOne <= m.UnscopedEnum.ETwo
99 assert m.UnscopedEnum.EOne <= 2
100 assert m.UnscopedEnum.ETwo >= m.UnscopedEnum.EOne
101 assert m.UnscopedEnum.ETwo >= 1
102 assert not (m.UnscopedEnum.ETwo < m.UnscopedEnum.EOne)
103 assert not (2 < m.UnscopedEnum.EOne)
Pim Schellart90d27802016-11-16 11:28:11 -0500104
Sergei Izmailov09f08292019-09-19 19:23:27 +0300105 # arithmetic
106 assert m.UnscopedEnum.EOne & m.UnscopedEnum.EThree == m.UnscopedEnum.EOne
107 assert m.UnscopedEnum.EOne | m.UnscopedEnum.ETwo == m.UnscopedEnum.EThree
108 assert m.UnscopedEnum.EOne ^ m.UnscopedEnum.EThree == m.UnscopedEnum.ETwo
109
Dean Moldovana9a37b42016-08-13 00:57:24 +0200110
111def test_scoped_enum():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400112 assert m.test_scoped_enum(m.ScopedEnum.Three) == "ScopedEnum::Three"
113 z = m.ScopedEnum.Two
114 assert m.test_scoped_enum(z) == "ScopedEnum::Two"
Dean Moldovana9a37b42016-08-13 00:57:24 +0200115
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300116 # Scoped enums will *NOT* accept ==/!= int comparisons (Will always return False)
117 assert not z == 3
118 assert not 3 == z
119 assert z != 3
120 assert 3 != z
Sergei Izmailov09f08292019-09-19 19:23:27 +0300121 # Compare with None
122 assert (z != None) # noqa: E711
123 assert not (z == None) # noqa: E711
124 # Compare with an object
125 assert (z != object())
126 assert not (z == object())
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300127 # Scoped enums will *NOT* accept >, <, >= and <= int comparisons (Will throw exceptions)
Dean Moldovana9a37b42016-08-13 00:57:24 +0200128 with pytest.raises(TypeError):
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300129 z > 3
Dean Moldovana9a37b42016-08-13 00:57:24 +0200130 with pytest.raises(TypeError):
Tarcísio Fischer54eb8192018-10-24 06:18:58 -0300131 z < 3
132 with pytest.raises(TypeError):
133 z >= 3
134 with pytest.raises(TypeError):
135 z <= 3
Dean Moldovana9a37b42016-08-13 00:57:24 +0200136
Pim Schellart90d27802016-11-16 11:28:11 -0500137 # order
Jason Rhinelander391c7542017-07-25 16:47:36 -0400138 assert m.ScopedEnum.Two < m.ScopedEnum.Three
139 assert m.ScopedEnum.Three > m.ScopedEnum.Two
140 assert m.ScopedEnum.Two <= m.ScopedEnum.Three
141 assert m.ScopedEnum.Two <= m.ScopedEnum.Two
142 assert m.ScopedEnum.Two >= m.ScopedEnum.Two
143 assert m.ScopedEnum.Three >= m.ScopedEnum.Two
Dean Moldovana9a37b42016-08-13 00:57:24 +0200144
Dean Moldovanbad17402016-11-20 21:21:54 +0100145
Dean Moldovana9a37b42016-08-13 00:57:24 +0200146def test_implicit_conversion():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400147 assert str(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "EMode.EFirstMode"
148 assert str(m.ClassWithUnscopedEnum.EFirstMode) == "EMode.EFirstMode"
David Vo5e6ec492020-09-20 09:12:19 +1000149 assert repr(m.ClassWithUnscopedEnum.EMode.EFirstMode) == "<EMode.EFirstMode: 1>"
150 assert repr(m.ClassWithUnscopedEnum.EFirstMode) == "<EMode.EFirstMode: 1>"
Dean Moldovana9a37b42016-08-13 00:57:24 +0200151
Jason Rhinelander391c7542017-07-25 16:47:36 -0400152 f = m.ClassWithUnscopedEnum.test_function
153 first = m.ClassWithUnscopedEnum.EFirstMode
154 second = m.ClassWithUnscopedEnum.ESecondMode
Dean Moldovana9a37b42016-08-13 00:57:24 +0200155
156 assert f(first) == 1
157
158 assert f(first) == f(first)
159 assert not f(first) != f(first)
160
161 assert f(first) != f(second)
162 assert not f(first) == f(second)
163
164 assert f(first) == int(f(first))
165 assert not f(first) != int(f(first))
166
167 assert f(first) != int(f(second))
168 assert not f(first) == int(f(second))
169
170 # noinspection PyDictCreation
171 x = {f(first): 1, f(second): 2}
172 x[f(first)] = 3
173 x[f(second)] = 4
174 # Hashing test
David Vo5e6ec492020-09-20 09:12:19 +1000175 assert repr(x) == "{<EMode.EFirstMode: 1>: 3, <EMode.ESecondMode: 2>: 4}"
Pim Schellart90d27802016-11-16 11:28:11 -0500176
Dean Moldovanbad17402016-11-20 21:21:54 +0100177
Pim Schellart90d27802016-11-16 11:28:11 -0500178def test_binary_operators():
Jason Rhinelander391c7542017-07-25 16:47:36 -0400179 assert int(m.Flags.Read) == 4
180 assert int(m.Flags.Write) == 2
181 assert int(m.Flags.Execute) == 1
182 assert int(m.Flags.Read | m.Flags.Write | m.Flags.Execute) == 7
183 assert int(m.Flags.Read | m.Flags.Write) == 6
184 assert int(m.Flags.Read | m.Flags.Execute) == 5
185 assert int(m.Flags.Write | m.Flags.Execute) == 3
186 assert int(m.Flags.Write | 1) == 3
Lori A. Burnsf6c4c102019-09-04 16:16:21 -0400187 assert ~m.Flags.Write == -3
Pim Schellart90d27802016-11-16 11:28:11 -0500188
Jason Rhinelander391c7542017-07-25 16:47:36 -0400189 state = m.Flags.Read | m.Flags.Write
190 assert (state & m.Flags.Read) != 0
191 assert (state & m.Flags.Write) != 0
192 assert (state & m.Flags.Execute) == 0
Pim Schellart90d27802016-11-16 11:28:11 -0500193 assert (state & 1) == 0
194
195 state2 = ~state
196 assert state2 == -7
197 assert int(state ^ state2) == -1
Wenzel Jakobe6fd2cd2017-04-28 14:46:52 +0200198
Wenzel Jakob7653a112017-04-28 22:43:14 +0200199
Wenzel Jakobe6fd2cd2017-04-28 14:46:52 +0200200def test_enum_to_int():
Wenzel Jakob31680e62019-09-20 11:06:10 +0200201 m.test_enum_to_int(m.Flags.Read)
202 m.test_enum_to_int(m.ClassWithUnscopedEnum.EMode.EFirstMode)
203 m.test_enum_to_uint(m.Flags.Read)
204 m.test_enum_to_uint(m.ClassWithUnscopedEnum.EMode.EFirstMode)
205 m.test_enum_to_long_long(m.Flags.Read)
206 m.test_enum_to_long_long(m.ClassWithUnscopedEnum.EMode.EFirstMode)
Krzysztof Fornalczyk5c8746f2018-09-11 10:59:56 +0200207
208
209def test_duplicate_enum_name():
210 with pytest.raises(ValueError) as excinfo:
211 m.register_bad_enum()
Wenzel Jakobf4245182018-09-01 01:20:24 +0200212 assert str(excinfo.value) == 'SimpleEnum: element "ONE" already exists!'