this repo has no description
at trunk 195 lines 5.7 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include <cerrno> 3#include <cmath> 4 5#include "Python.h" 6#include "gtest/gtest.h" 7 8#include "capi-fixture.h" 9#include "capi-testing.h" 10 11namespace py { 12namespace testing { 13 14using ComplexExtensionApiTest = ExtensionApi; 15 16TEST_F(ComplexExtensionApiTest, PyCAbsReturnsComplexAbsoluteValue) { 17 EXPECT_EQ(_Py_c_abs({12, 0}), 12); 18 EXPECT_EQ(_Py_c_abs({0, 34}), 34); 19 EXPECT_EQ(_Py_c_abs({INFINITY, 56}), INFINITY); 20 EXPECT_EQ(_Py_c_abs({-INFINITY, 78}), INFINITY); 21 EXPECT_EQ(_Py_c_abs({90, INFINITY}), INFINITY); 22 EXPECT_EQ(_Py_c_abs({123, -INFINITY}), INFINITY); 23 EXPECT_TRUE(std::isnan(_Py_c_abs({456, NAN}))); 24 EXPECT_TRUE(std::isnan(_Py_c_abs({NAN, 789}))); 25} 26 27TEST_F(ComplexExtensionApiTest, PyCDiffReturnsComplexDifference) { 28 Py_complex diff = _Py_c_diff({2.0, 5.0}, {4.0, -3.0}); 29 EXPECT_EQ(diff.real, -2.0); 30 EXPECT_EQ(diff.imag, 8.0); 31} 32 33TEST_F(ComplexExtensionApiTest, PyCNegReturnsComplexNegation) { 34 Py_complex neg = _Py_c_neg({-123.0, 456.0}); 35 EXPECT_EQ(neg.real, 123.0); 36 EXPECT_EQ(neg.imag, -456); 37} 38 39TEST_F(ComplexExtensionApiTest, PyCProdReturnsComplexProduct) { 40 Py_complex prod = _Py_c_prod({1.0, -2.0}, {-3.0, 4.0}); 41 EXPECT_EQ(prod.real, 5.0); 42 EXPECT_EQ(prod.imag, 10.0); 43} 44 45TEST_F(ComplexExtensionApiTest, PyCQuotReturnsComplexQuotient) { 46 // rhs.real > rhs.imag 47 errno = 0; 48 Py_complex q1 = _Py_c_quot({10, 20}, {2, 1}); 49 EXPECT_EQ(errno, 0); 50 EXPECT_EQ(q1.real, 8.0); 51 EXPECT_EQ(q1.imag, 6.0); 52 53 // rhs.imag > rhs.real 54 errno = 0; 55 Py_complex q2 = _Py_c_quot({10, 20}, {1, 2}); 56 EXPECT_EQ(errno, 0); 57 EXPECT_EQ(q2.real, 10.0); 58 EXPECT_EQ(q2.imag, 0.0); 59 60 // rhs.real = 0 61 errno = 0; 62 Py_complex q3 = _Py_c_quot({10, 10}, {0, 0}); 63 EXPECT_EQ(errno, EDOM); 64 EXPECT_EQ(q3.real, 0.0); 65 EXPECT_EQ(q3.imag, 0.0); 66 67 // NAN 68 errno = 0; 69 Py_complex q4 = _Py_c_quot({1, 2}, {NAN, 4}); 70 EXPECT_EQ(errno, 0); 71 EXPECT_TRUE(std::isnan(q4.real)); 72 EXPECT_TRUE(std::isnan(q4.imag)); 73} 74 75TEST_F(ComplexExtensionApiTest, PyCSumReturnsComplexSum) { 76 Py_complex sum = _Py_c_sum({2.0, 5.0}, {4.0, -3.0}); 77 EXPECT_EQ(sum.real, 6.0); 78 EXPECT_EQ(sum.imag, 2.0); 79} 80 81TEST_F(ComplexExtensionApiTest, AsCComplexWithComplexReturnsValue) { 82 PyObjectPtr cmp(PyComplex_FromDoubles(1.0, 0.0)); 83 Py_complex result = PyComplex_AsCComplex(cmp); 84 ASSERT_EQ(PyErr_Occurred(), nullptr); 85 EXPECT_EQ(result.real, 1.0); 86 EXPECT_EQ(result.imag, 0.0); 87} 88 89TEST_F(ComplexExtensionApiTest, 90 AsComplexWithRaisingDescriptorPropagatesException) { 91 PyRun_SimpleString(R"( 92class Desc: 93 def __get__(self, owner, fn): 94 raise UserWarning("foo") 95 def __call__(self, *args, **kwargs): 96 raise "foo" 97class Foo: 98 __complex__ = Desc() 99foo = Foo() 100)"); 101 PyObjectPtr foo(mainModuleGet("foo")); 102 Py_complex result = PyComplex_AsCComplex(foo); 103 EXPECT_EQ(result.real, -1.0); 104 EXPECT_EQ(result.imag, 0.0); 105 ASSERT_NE(PyErr_Occurred(), nullptr); 106 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning)); 107} 108 109TEST_F(ComplexExtensionApiTest, 110 AsComplexWithMistypedDunderComplexRaisesTypeError) { 111 PyRun_SimpleString(R"( 112class Foo: 113 def __complex__(self): 114 return 1 115foo = Foo() 116)"); 117 PyObjectPtr foo(mainModuleGet("foo")); 118 Py_complex result = PyComplex_AsCComplex(foo); 119 ASSERT_NE(PyErr_Occurred(), nullptr); 120 ASSERT_EQ(result.real, -1.0); 121 ASSERT_EQ(result.imag, 0.0); 122 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 123} 124 125TEST_F(ComplexExtensionApiTest, AsComplexWithDunderComplexReturnsValue) { 126 PyRun_SimpleString(R"( 127class Foo: 128 def __complex__(self): 129 return 1+0j 130foo = Foo() 131)"); 132 PyObjectPtr foo(mainModuleGet("foo")); 133 Py_complex result = PyComplex_AsCComplex(foo); 134 ASSERT_EQ(PyErr_Occurred(), nullptr); 135 EXPECT_EQ(result.real, 1.0); 136 EXPECT_EQ(result.imag, 0.0); 137} 138 139TEST_F(ComplexExtensionApiTest, AsCComplexWithFloatReturnsRealValue) { 140 PyObjectPtr flt(PyFloat_FromDouble(1.0)); 141 Py_complex result = PyComplex_AsCComplex(flt); 142 ASSERT_EQ(PyErr_Occurred(), nullptr); 143 EXPECT_EQ(result.real, 1.0); 144 EXPECT_EQ(result.imag, 0.0); 145} 146 147TEST_F(ComplexExtensionApiTest, FromDoublesReturnsComplex) { 148 PyObjectPtr cmp(PyComplex_FromDoubles(0.0, 0.0)); 149 EXPECT_TRUE(PyComplex_CheckExact(cmp)); 150} 151 152TEST_F(ComplexExtensionApiTest, FromCComplexReturnsComplex) { 153 Py_complex c = {1.0, 0.0}; 154 PyObjectPtr cmp(PyComplex_FromCComplex(c)); 155 EXPECT_TRUE(PyComplex_CheckExact(cmp)); 156} 157 158TEST_F(ComplexExtensionApiTest, ImagAsDoubleWithComplexReturnsValue) { 159 PyObjectPtr cmp(PyComplex_FromDoubles(0.0, 1.0)); 160 double result = PyComplex_ImagAsDouble(cmp); 161 ASSERT_EQ(PyErr_Occurred(), nullptr); 162 EXPECT_EQ(result, 1.0); 163} 164 165TEST_F(ComplexExtensionApiTest, ImagAsDoubleWithNonComplexReturnsZero) { 166 PyObjectPtr flt(PyFloat_FromDouble(1.0)); 167 double result = PyComplex_ImagAsDouble(flt); 168 ASSERT_EQ(PyErr_Occurred(), nullptr); 169 EXPECT_EQ(result, 0.0); 170} 171 172TEST_F(ComplexExtensionApiTest, RealAsDoubleWithComplexReturnsValue) { 173 PyObjectPtr cmp(PyComplex_FromDoubles(1.0, 0.0)); 174 double result = PyComplex_RealAsDouble(cmp); 175 ASSERT_EQ(PyErr_Occurred(), nullptr); 176 EXPECT_EQ(result, 1.0); 177} 178 179TEST_F(ComplexExtensionApiTest, RealAsDoubleWithFloatReturnsFloatValue) { 180 PyObjectPtr flt(PyFloat_FromDouble(1.0)); 181 double result = PyComplex_RealAsDouble(flt); 182 ASSERT_EQ(PyErr_Occurred(), nullptr); 183 EXPECT_EQ(result, 1.0); 184} 185 186TEST_F(ComplexExtensionApiTest, RealAsDoubleWithNonFloatRaisesTypeError) { 187 PyObjectPtr foo(PyTuple_New(0)); 188 double result = PyComplex_RealAsDouble(foo); 189 ASSERT_NE(PyErr_Occurred(), nullptr); 190 ASSERT_EQ(result, -1.0); 191 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 192} 193 194} // namespace testing 195} // namespace py