122c8efcdSZachary Turner //===-- PythonDataObjectsTests.cpp ------------------------------*- C++ -*-===//
222c8efcdSZachary Turner //
322c8efcdSZachary Turner //                     The LLVM Compiler Infrastructure
422c8efcdSZachary Turner //
522c8efcdSZachary Turner // This file is distributed under the University of Illinois Open Source
622c8efcdSZachary Turner // License. See LICENSE.TXT for details.
722c8efcdSZachary Turner //
822c8efcdSZachary Turner //===----------------------------------------------------------------------===//
922c8efcdSZachary Turner 
1022c8efcdSZachary Turner #include "gtest/gtest.h"
1122c8efcdSZachary Turner 
129c40264fSZachary Turner #include "lldb/Host/File.h"
139c40264fSZachary Turner #include "lldb/Host/FileSystem.h"
1422c8efcdSZachary Turner #include "lldb/Host/HostInfo.h"
1522c8efcdSZachary Turner #include "Plugins/ScriptInterpreter/Python/lldb-python.h"
1622c8efcdSZachary Turner #include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h"
1722c8efcdSZachary Turner #include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h"
1822c8efcdSZachary Turner 
1922c8efcdSZachary Turner using namespace lldb_private;
2022c8efcdSZachary Turner 
2122c8efcdSZachary Turner class PythonDataObjectsTest : public testing::Test
2222c8efcdSZachary Turner {
2322c8efcdSZachary Turner   public:
2422c8efcdSZachary Turner     void
2522c8efcdSZachary Turner     SetUp() override
2622c8efcdSZachary Turner     {
2722c8efcdSZachary Turner         HostInfoBase::Initialize();
28f8b22f8fSZachary Turner         // ScriptInterpreterPython::Initialize() depends on HostInfo being
29f8b22f8fSZachary Turner         // initializedso it can compute the python directory etc.
3022c8efcdSZachary Turner         ScriptInterpreterPython::Initialize();
31f8b22f8fSZachary Turner 
32f8b22f8fSZachary Turner         // Although we don't care about concurrency for the purposes of running
33f8b22f8fSZachary Turner         // this test suite, Python requires the GIL to be locked even for
34f8b22f8fSZachary Turner         // deallocating memory, which can happen when you call Py_DECREF or
35f8b22f8fSZachary Turner         // Py_INCREF.  So acquire the GIL for the entire duration of this
36f8b22f8fSZachary Turner         // test suite.
37f8b22f8fSZachary Turner         m_gil_state = PyGILState_Ensure();
3822c8efcdSZachary Turner     }
3922c8efcdSZachary Turner 
4022c8efcdSZachary Turner     void
4122c8efcdSZachary Turner     TearDown() override
4222c8efcdSZachary Turner     {
43f8b22f8fSZachary Turner         PyGILState_Release(m_gil_state);
44f8b22f8fSZachary Turner 
4522c8efcdSZachary Turner         ScriptInterpreterPython::Terminate();
4622c8efcdSZachary Turner     }
47f8b22f8fSZachary Turner 
48f8b22f8fSZachary Turner   private:
49f8b22f8fSZachary Turner     PyGILState_STATE m_gil_state;
5022c8efcdSZachary Turner };
5122c8efcdSZachary Turner 
52f8b22f8fSZachary Turner TEST_F(PythonDataObjectsTest, TestOwnedReferences)
53f8b22f8fSZachary Turner {
5418426935SZachary Turner     // After creating a new object, the refcount should be >= 1
55f8b22f8fSZachary Turner     PyObject *obj = PyLong_FromLong(3);
5618426935SZachary Turner     Py_ssize_t original_refcnt = obj->ob_refcnt;
5718426935SZachary Turner     EXPECT_LE(1, original_refcnt);
58f8b22f8fSZachary Turner 
5918426935SZachary Turner     // If we take an owned reference, the refcount should be the same
60f8b22f8fSZachary Turner     PythonObject owned_long(PyRefType::Owned, obj);
6118426935SZachary Turner     EXPECT_EQ(original_refcnt, owned_long.get()->ob_refcnt);
62f8b22f8fSZachary Turner 
6318426935SZachary Turner     // Take another reference and verify that the refcount increases by 1
64f8b22f8fSZachary Turner     PythonObject strong_ref(owned_long);
6518426935SZachary Turner     EXPECT_EQ(original_refcnt + 1, strong_ref.get()->ob_refcnt);
66f8b22f8fSZachary Turner 
6718426935SZachary Turner     // If we reset the first one, the refcount should be the original value.
68f8b22f8fSZachary Turner     owned_long.Reset();
6918426935SZachary Turner     EXPECT_EQ(original_refcnt, strong_ref.get()->ob_refcnt);
70f8b22f8fSZachary Turner }
71f8b22f8fSZachary Turner 
72f8b22f8fSZachary Turner TEST_F(PythonDataObjectsTest, TestResetting)
73f8b22f8fSZachary Turner {
74f8b22f8fSZachary Turner     PythonDictionary dict(PyInitialValue::Empty);
75f8b22f8fSZachary Turner 
76f8b22f8fSZachary Turner     PyObject *new_dict = PyDict_New();
77f8b22f8fSZachary Turner     dict.Reset(PyRefType::Owned, new_dict);
78f8b22f8fSZachary Turner     EXPECT_EQ(new_dict, dict.get());
79f8b22f8fSZachary Turner 
80f8b22f8fSZachary Turner     dict.Reset(PyRefType::Owned, nullptr);
81f8b22f8fSZachary Turner     EXPECT_EQ(nullptr, dict.get());
82f8b22f8fSZachary Turner 
83f8b22f8fSZachary Turner     dict.Reset(PyRefType::Owned, PyDict_New());
84f8b22f8fSZachary Turner     EXPECT_NE(nullptr, dict.get());
85f8b22f8fSZachary Turner     dict.Reset();
86f8b22f8fSZachary Turner     EXPECT_EQ(nullptr, dict.get());
87f8b22f8fSZachary Turner }
88f8b22f8fSZachary Turner 
89f8b22f8fSZachary Turner TEST_F(PythonDataObjectsTest, TestBorrowedReferences)
90f8b22f8fSZachary Turner {
91f8b22f8fSZachary Turner     PythonInteger long_value(PyRefType::Owned, PyLong_FromLong(3));
9218426935SZachary Turner     Py_ssize_t original_refcnt = long_value.get()->ob_refcnt;
9318426935SZachary Turner     EXPECT_LE(1, original_refcnt);
94f8b22f8fSZachary Turner 
95f8b22f8fSZachary Turner     PythonInteger borrowed_long(PyRefType::Borrowed, long_value.get());
9618426935SZachary Turner     EXPECT_EQ(original_refcnt + 1, borrowed_long.get()->ob_refcnt);
97f8b22f8fSZachary Turner }
98f8b22f8fSZachary Turner 
99*7841efbbSZachary Turner TEST_F(PythonDataObjectsTest, TestGlobalNameResolutionNoDot)
100*7841efbbSZachary Turner {
101*7841efbbSZachary Turner     PythonObject sys_module = PythonObject::ResolveNameGlobal("sys");
102*7841efbbSZachary Turner     EXPECT_TRUE(sys_module.IsAllocated());
103*7841efbbSZachary Turner     EXPECT_TRUE(PythonModule::Check(sys_module.get()));
104*7841efbbSZachary Turner }
105*7841efbbSZachary Turner 
106*7841efbbSZachary Turner TEST_F(PythonDataObjectsTest, TestModuleNameResolutionNoDot)
107*7841efbbSZachary Turner {
108*7841efbbSZachary Turner     PythonObject sys_module = PythonObject::ResolveNameGlobal("sys");
109*7841efbbSZachary Turner     PythonObject sys_path = sys_module.ResolveName("path");
110*7841efbbSZachary Turner     PythonObject sys_version_info = sys_module.ResolveName("version_info");
111*7841efbbSZachary Turner     EXPECT_TRUE(sys_path.IsAllocated());
112*7841efbbSZachary Turner     EXPECT_TRUE(sys_version_info.IsAllocated());
113*7841efbbSZachary Turner 
114*7841efbbSZachary Turner     EXPECT_TRUE(PythonList::Check(sys_path.get()));
115*7841efbbSZachary Turner }
116*7841efbbSZachary Turner 
117*7841efbbSZachary Turner TEST_F(PythonDataObjectsTest, TestTypeNameResolutionNoDot)
118*7841efbbSZachary Turner {
119*7841efbbSZachary Turner     PythonObject sys_module = PythonObject::ResolveNameGlobal("sys");
120*7841efbbSZachary Turner     PythonObject sys_version_info = sys_module.ResolveName("version_info");
121*7841efbbSZachary Turner 
122*7841efbbSZachary Turner     PythonObject version_info_type(PyRefType::Owned, PyObject_Type(sys_version_info.get()));
123*7841efbbSZachary Turner     EXPECT_TRUE(version_info_type.IsAllocated());
124*7841efbbSZachary Turner     PythonObject major_version_field = version_info_type.ResolveName("major");
125*7841efbbSZachary Turner     EXPECT_TRUE(major_version_field.IsAllocated());
126*7841efbbSZachary Turner }
127*7841efbbSZachary Turner 
128*7841efbbSZachary Turner TEST_F(PythonDataObjectsTest, TestInstanceNameResolutionNoDot)
129*7841efbbSZachary Turner {
130*7841efbbSZachary Turner     PythonObject sys_module = PythonObject::ResolveNameGlobal("sys");
131*7841efbbSZachary Turner     PythonObject sys_version_info = sys_module.ResolveName("version_info");
132*7841efbbSZachary Turner     PythonObject major_version_field = sys_version_info.ResolveName("major");
133*7841efbbSZachary Turner     PythonObject minor_version_field = sys_version_info.ResolveName("minor");
134*7841efbbSZachary Turner 
135*7841efbbSZachary Turner     EXPECT_TRUE(major_version_field.IsAllocated());
136*7841efbbSZachary Turner     EXPECT_TRUE(minor_version_field.IsAllocated());
137*7841efbbSZachary Turner 
138*7841efbbSZachary Turner     PythonInteger major_version_value = major_version_field.AsType<PythonInteger>();
139*7841efbbSZachary Turner     PythonInteger minor_version_value = minor_version_field.AsType<PythonInteger>();
140*7841efbbSZachary Turner 
141*7841efbbSZachary Turner     EXPECT_EQ(PY_MAJOR_VERSION, major_version_value.GetInteger());
142*7841efbbSZachary Turner     EXPECT_EQ(PY_MINOR_VERSION, minor_version_value.GetInteger());
143*7841efbbSZachary Turner }
144*7841efbbSZachary Turner 
145*7841efbbSZachary Turner TEST_F(PythonDataObjectsTest, TestGlobalNameResolutionWithDot)
146*7841efbbSZachary Turner {
147*7841efbbSZachary Turner     PythonObject sys_path = PythonObject::ResolveNameGlobal("sys.path");
148*7841efbbSZachary Turner     EXPECT_TRUE(sys_path.IsAllocated());
149*7841efbbSZachary Turner     EXPECT_TRUE(PythonList::Check(sys_path.get()));
150*7841efbbSZachary Turner 
151*7841efbbSZachary Turner     PythonInteger version_major = PythonObject::ResolveNameGlobal("sys.version_info.major").AsType<PythonInteger>();
152*7841efbbSZachary Turner     PythonInteger version_minor = PythonObject::ResolveNameGlobal("sys.version_info.minor").AsType<PythonInteger>();
153*7841efbbSZachary Turner     EXPECT_TRUE(version_major.IsAllocated());
154*7841efbbSZachary Turner     EXPECT_TRUE(version_minor.IsAllocated());
155*7841efbbSZachary Turner     EXPECT_EQ(PY_MAJOR_VERSION, version_major.GetInteger());
156*7841efbbSZachary Turner     EXPECT_EQ(PY_MINOR_VERSION, version_minor.GetInteger());
157*7841efbbSZachary Turner }
158*7841efbbSZachary Turner 
15922c8efcdSZachary Turner TEST_F(PythonDataObjectsTest, TestPythonInteger)
16022c8efcdSZachary Turner {
16122c8efcdSZachary Turner // Test that integers behave correctly when wrapped by a PythonInteger.
16222c8efcdSZachary Turner 
16322c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
16422c8efcdSZachary Turner     // Verify that `PythonInt` works correctly when given a PyInt object.
16522c8efcdSZachary Turner     // Note that PyInt doesn't exist in Python 3.x, so this is only for 2.x
16622c8efcdSZachary Turner     PyObject *py_int = PyInt_FromLong(12);
16722c8efcdSZachary Turner     EXPECT_TRUE(PythonInteger::Check(py_int));
168f8b22f8fSZachary Turner     PythonInteger python_int(PyRefType::Owned, py_int);
16922c8efcdSZachary Turner 
17022c8efcdSZachary Turner     EXPECT_EQ(PyObjectType::Integer, python_int.GetObjectType());
17122c8efcdSZachary Turner     EXPECT_EQ(12, python_int.GetInteger());
17222c8efcdSZachary Turner #endif
17322c8efcdSZachary Turner 
17418426935SZachary Turner     // Verify that `PythonInteger` works correctly when given a PyLong object.
17522c8efcdSZachary Turner     PyObject *py_long = PyLong_FromLong(12);
17622c8efcdSZachary Turner     EXPECT_TRUE(PythonInteger::Check(py_long));
177f8b22f8fSZachary Turner     PythonInteger python_long(PyRefType::Owned, py_long);
17822c8efcdSZachary Turner     EXPECT_EQ(PyObjectType::Integer, python_long.GetObjectType());
17922c8efcdSZachary Turner 
18022c8efcdSZachary Turner     // Verify that you can reset the value and that it is reflected properly.
18122c8efcdSZachary Turner     python_long.SetInteger(40);
18222c8efcdSZachary Turner     EXPECT_EQ(40, python_long.GetInteger());
18318426935SZachary Turner 
18418426935SZachary Turner     // Test that creating a `PythonInteger` object works correctly with the
18518426935SZachary Turner     // int constructor.
18618426935SZachary Turner     PythonInteger constructed_int(7);
18718426935SZachary Turner     EXPECT_EQ(7, constructed_int.GetInteger());
18822c8efcdSZachary Turner }
18922c8efcdSZachary Turner 
19022c8efcdSZachary Turner TEST_F(PythonDataObjectsTest, TestPythonString)
19122c8efcdSZachary Turner {
19222c8efcdSZachary Turner     // Test that strings behave correctly when wrapped by a PythonString.
19322c8efcdSZachary Turner 
19418426935SZachary Turner     static const char *test_string = "PythonDataObjectsTest::TestPythonString1";
19518426935SZachary Turner     static const char *test_string2 = "PythonDataObjectsTest::TestPythonString2";
19618426935SZachary Turner     static const char *test_string3 = "PythonDataObjectsTest::TestPythonString3";
19722c8efcdSZachary Turner 
19822c8efcdSZachary Turner #if PY_MAJOR_VERSION < 3
19922c8efcdSZachary Turner     // Verify that `PythonString` works correctly when given a PyString object.
20022c8efcdSZachary Turner     // Note that PyString doesn't exist in Python 3.x, so this is only for 2.x
20122c8efcdSZachary Turner     PyObject *py_string = PyString_FromString(test_string);
20222c8efcdSZachary Turner     EXPECT_TRUE(PythonString::Check(py_string));
203f8b22f8fSZachary Turner     PythonString python_string(PyRefType::Owned, py_string);
20422c8efcdSZachary Turner 
20522c8efcdSZachary Turner     EXPECT_EQ(PyObjectType::String, python_string.GetObjectType());
20622c8efcdSZachary Turner     EXPECT_STREQ(test_string, python_string.GetString().data());
20718426935SZachary Turner #else
20822c8efcdSZachary Turner     // Verify that `PythonString` works correctly when given a PyUnicode object.
20922c8efcdSZachary Turner     PyObject *py_unicode = PyUnicode_FromString(test_string);
21022c8efcdSZachary Turner     EXPECT_TRUE(PythonString::Check(py_unicode));
211f8b22f8fSZachary Turner     PythonString python_unicode(PyRefType::Owned, py_unicode);
21222c8efcdSZachary Turner     EXPECT_EQ(PyObjectType::String, python_unicode.GetObjectType());
21322c8efcdSZachary Turner     EXPECT_STREQ(test_string, python_unicode.GetString().data());
21418426935SZachary Turner #endif
21522c8efcdSZachary Turner 
21618426935SZachary Turner     // Test that creating a `PythonString` object works correctly with the
21718426935SZachary Turner     // string constructor
21818426935SZachary Turner     PythonString constructed_string(test_string3);
21918426935SZachary Turner     EXPECT_STREQ(test_string3, constructed_string.GetString().str().c_str());
22022c8efcdSZachary Turner }
22122c8efcdSZachary Turner 
22218426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonStringToStr)
22318426935SZachary Turner {
22418426935SZachary Turner     const char *c_str = "PythonDataObjectsTest::TestPythonStringToStr";
22518426935SZachary Turner 
22618426935SZachary Turner     PythonString str(c_str);
22718426935SZachary Turner     EXPECT_STREQ(c_str, str.GetString().str().c_str());
22818426935SZachary Turner 
22918426935SZachary Turner     PythonString str_str = str.Str();
23018426935SZachary Turner     EXPECT_STREQ(c_str, str_str.GetString().str().c_str());
23118426935SZachary Turner }
23218426935SZachary Turner 
23318426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonIntegerToStr)
23418426935SZachary Turner {
23518426935SZachary Turner }
23618426935SZachary Turner 
23718426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonIntegerToStructuredInteger)
23818426935SZachary Turner {
23918426935SZachary Turner     PythonInteger integer(7);
24018426935SZachary Turner     auto int_sp = integer.CreateStructuredInteger();
24118426935SZachary Turner     EXPECT_EQ(7, int_sp->GetValue());
24218426935SZachary Turner }
24318426935SZachary Turner 
24418426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonStringToStructuredString)
24518426935SZachary Turner {
24618426935SZachary Turner     static const char *test_string = "PythonDataObjectsTest::TestPythonStringToStructuredString";
24718426935SZachary Turner     PythonString constructed_string(test_string);
24818426935SZachary Turner     auto string_sp = constructed_string.CreateStructuredString();
24918426935SZachary Turner     EXPECT_STREQ(test_string, string_sp->GetStringValue().c_str());
25018426935SZachary Turner }
25118426935SZachary Turner 
25218426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonListValueEquality)
25322c8efcdSZachary Turner {
25422c8efcdSZachary Turner     // Test that a list which is built through the native
25522c8efcdSZachary Turner     // Python API behaves correctly when wrapped by a PythonList.
25622c8efcdSZachary Turner     static const int list_size = 2;
25718426935SZachary Turner     static const long long_value0 = 5;
25818426935SZachary Turner     static const char *const string_value1 = "String Index 1";
25922c8efcdSZachary Turner 
26022c8efcdSZachary Turner     PyObject *py_list = PyList_New(2);
261f8b22f8fSZachary Turner     EXPECT_TRUE(PythonList::Check(py_list));
262f8b22f8fSZachary Turner     PythonList list(PyRefType::Owned, py_list);
263f8b22f8fSZachary Turner 
264f8b22f8fSZachary Turner     PythonObject list_items[list_size];
26518426935SZachary Turner     list_items[0].Reset(PythonInteger(long_value0));
26618426935SZachary Turner     list_items[1].Reset(PythonString(string_value1));
26722c8efcdSZachary Turner 
26822c8efcdSZachary Turner     for (int i = 0; i < list_size; ++i)
269f8b22f8fSZachary Turner         list.SetItemAtIndex(i, list_items[i]);
27022c8efcdSZachary Turner 
27122c8efcdSZachary Turner     EXPECT_EQ(list_size, list.GetSize());
27222c8efcdSZachary Turner     EXPECT_EQ(PyObjectType::List, list.GetObjectType());
27322c8efcdSZachary Turner 
27418426935SZachary Turner     // Verify that the values match
27518426935SZachary Turner     PythonObject chk_value1 = list.GetItemAtIndex(0);
27618426935SZachary Turner     PythonObject chk_value2 = list.GetItemAtIndex(1);
27718426935SZachary Turner     EXPECT_TRUE(PythonInteger::Check(chk_value1.get()));
27818426935SZachary Turner     EXPECT_TRUE(PythonString::Check(chk_value2.get()));
27922c8efcdSZachary Turner 
28018426935SZachary Turner     PythonInteger chk_int(PyRefType::Borrowed, chk_value1.get());
28118426935SZachary Turner     PythonString chk_str(PyRefType::Borrowed, chk_value2.get());
28222c8efcdSZachary Turner 
28318426935SZachary Turner     EXPECT_EQ(long_value0, chk_int.GetInteger());
28418426935SZachary Turner     EXPECT_STREQ(string_value1, chk_str.GetString().str().c_str());
28522c8efcdSZachary Turner }
28622c8efcdSZachary Turner 
28722c8efcdSZachary Turner TEST_F(PythonDataObjectsTest, TestPythonListManipulation)
28822c8efcdSZachary Turner {
28922c8efcdSZachary Turner     // Test that manipulation of a PythonList behaves correctly when
29022c8efcdSZachary Turner     // wrapped by a PythonDictionary.
29122c8efcdSZachary Turner 
29218426935SZachary Turner     static const long long_value0 = 5;
29318426935SZachary Turner     static const char *const string_value1 = "String Index 1";
29422c8efcdSZachary Turner 
295f8b22f8fSZachary Turner     PythonList list(PyInitialValue::Empty);
29618426935SZachary Turner     PythonInteger integer(long_value0);
29718426935SZachary Turner     PythonString string(string_value1);
29822c8efcdSZachary Turner 
29922c8efcdSZachary Turner     list.AppendItem(integer);
30022c8efcdSZachary Turner     list.AppendItem(string);
30122c8efcdSZachary Turner     EXPECT_EQ(2, list.GetSize());
30222c8efcdSZachary Turner 
30318426935SZachary Turner     // Verify that the values match
30418426935SZachary Turner     PythonObject chk_value1 = list.GetItemAtIndex(0);
30518426935SZachary Turner     PythonObject chk_value2 = list.GetItemAtIndex(1);
30618426935SZachary Turner     EXPECT_TRUE(PythonInteger::Check(chk_value1.get()));
30718426935SZachary Turner     EXPECT_TRUE(PythonString::Check(chk_value2.get()));
30818426935SZachary Turner 
30918426935SZachary Turner     PythonInteger chk_int(PyRefType::Borrowed, chk_value1.get());
31018426935SZachary Turner     PythonString chk_str(PyRefType::Borrowed, chk_value2.get());
31118426935SZachary Turner 
31218426935SZachary Turner     EXPECT_EQ(long_value0, chk_int.GetInteger());
31318426935SZachary Turner     EXPECT_STREQ(string_value1, chk_str.GetString().str().c_str());
31418426935SZachary Turner }
31518426935SZachary Turner 
31618426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonListToStructuredList)
31718426935SZachary Turner {
31818426935SZachary Turner     static const long long_value0 = 5;
31918426935SZachary Turner     static const char *const string_value1 = "String Index 1";
32018426935SZachary Turner 
32118426935SZachary Turner     PythonList list(PyInitialValue::Empty);
32218426935SZachary Turner     list.AppendItem(PythonInteger(long_value0));
32318426935SZachary Turner     list.AppendItem(PythonString(string_value1));
32418426935SZachary Turner 
32518426935SZachary Turner     auto array_sp = list.CreateStructuredArray();
32618426935SZachary Turner     EXPECT_EQ(StructuredData::Type::eTypeInteger, array_sp->GetItemAtIndex(0)->GetType());
32718426935SZachary Turner     EXPECT_EQ(StructuredData::Type::eTypeString, array_sp->GetItemAtIndex(1)->GetType());
32818426935SZachary Turner 
32918426935SZachary Turner     auto int_sp = array_sp->GetItemAtIndex(0)->GetAsInteger();
33018426935SZachary Turner     auto string_sp = array_sp->GetItemAtIndex(1)->GetAsString();
33118426935SZachary Turner 
33218426935SZachary Turner     EXPECT_EQ(long_value0, int_sp->GetValue());
33318426935SZachary Turner     EXPECT_STREQ(string_value1, string_sp->GetValue().c_str());
33418426935SZachary Turner }
33518426935SZachary Turner 
33618426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonDictionaryValueEquality)
33718426935SZachary Turner {
33818426935SZachary Turner     // Test that a dictionary which is built through the native
33918426935SZachary Turner     // Python API behaves correctly when wrapped by a PythonDictionary.
34018426935SZachary Turner     static const int dict_entries = 2;
34118426935SZachary Turner     const char *key_0 = "Key 0";
34218426935SZachary Turner     int key_1 = 1;
34318426935SZachary Turner     const int value_0 = 0;
34418426935SZachary Turner     const char *value_1 = "Value 1";
34518426935SZachary Turner 
34618426935SZachary Turner     PythonObject py_keys[dict_entries];
34718426935SZachary Turner     PythonObject py_values[dict_entries];
34818426935SZachary Turner 
34918426935SZachary Turner     py_keys[0].Reset(PythonString(key_0));
35018426935SZachary Turner     py_keys[1].Reset(PythonInteger(key_1));
35118426935SZachary Turner     py_values[0].Reset(PythonInteger(value_0));
35218426935SZachary Turner     py_values[1].Reset(PythonString(value_1));
35318426935SZachary Turner 
35418426935SZachary Turner     PyObject *py_dict = PyDict_New();
35518426935SZachary Turner     EXPECT_TRUE(PythonDictionary::Check(py_dict));
35618426935SZachary Turner     PythonDictionary dict(PyRefType::Owned, py_dict);
35718426935SZachary Turner 
35818426935SZachary Turner     for (int i = 0; i < dict_entries; ++i)
35918426935SZachary Turner         PyDict_SetItem(py_dict, py_keys[i].get(), py_values[i].get());
36018426935SZachary Turner     EXPECT_EQ(dict.GetSize(), dict_entries);
36118426935SZachary Turner     EXPECT_EQ(PyObjectType::Dictionary, dict.GetObjectType());
36218426935SZachary Turner 
36318426935SZachary Turner     // Verify that the values match
36418426935SZachary Turner     PythonObject chk_value1 = dict.GetItemForKey(py_keys[0]);
36518426935SZachary Turner     PythonObject chk_value2 = dict.GetItemForKey(py_keys[1]);
36618426935SZachary Turner     EXPECT_TRUE(PythonInteger::Check(chk_value1.get()));
36718426935SZachary Turner     EXPECT_TRUE(PythonString::Check(chk_value2.get()));
36818426935SZachary Turner 
36918426935SZachary Turner     PythonInteger chk_int(PyRefType::Borrowed, chk_value1.get());
37018426935SZachary Turner     PythonString chk_str(PyRefType::Borrowed, chk_value2.get());
37118426935SZachary Turner 
37218426935SZachary Turner     EXPECT_EQ(value_0, chk_int.GetInteger());
37318426935SZachary Turner     EXPECT_STREQ(value_1, chk_str.GetString().str().c_str());
37422c8efcdSZachary Turner }
37522c8efcdSZachary Turner 
37622c8efcdSZachary Turner TEST_F(PythonDataObjectsTest, TestPythonDictionaryManipulation)
37722c8efcdSZachary Turner {
37822c8efcdSZachary Turner     // Test that manipulation of a dictionary behaves correctly when wrapped
37922c8efcdSZachary Turner     // by a PythonDictionary.
38022c8efcdSZachary Turner     static const int dict_entries = 2;
38122c8efcdSZachary Turner 
38218426935SZachary Turner     const char *const key_0 = "Key 0";
38318426935SZachary Turner     const char *const key_1 = "Key 1";
38418426935SZachary Turner     const long value_0 = 1;
38518426935SZachary Turner     const char *const value_1 = "Value 1";
38618426935SZachary Turner 
387f8b22f8fSZachary Turner     PythonString keys[dict_entries];
388f8b22f8fSZachary Turner     PythonObject values[dict_entries];
38922c8efcdSZachary Turner 
39018426935SZachary Turner     keys[0].Reset(PythonString(key_0));
39118426935SZachary Turner     keys[1].Reset(PythonString(key_1));
39218426935SZachary Turner     values[0].Reset(PythonInteger(value_0));
39318426935SZachary Turner     values[1].Reset(PythonString(value_1));
39422c8efcdSZachary Turner 
395f8b22f8fSZachary Turner     PythonDictionary dict(PyInitialValue::Empty);
39622c8efcdSZachary Turner     for (int i = 0; i < 2; ++i)
397f8b22f8fSZachary Turner         dict.SetItemForKey(keys[i], values[i]);
39822c8efcdSZachary Turner 
39922c8efcdSZachary Turner     EXPECT_EQ(dict_entries, dict.GetSize());
40022c8efcdSZachary Turner 
40118426935SZachary Turner     // Verify that the keys and values match
40218426935SZachary Turner     PythonObject chk_value1 = dict.GetItemForKey(keys[0]);
40318426935SZachary Turner     PythonObject chk_value2 = dict.GetItemForKey(keys[1]);
40418426935SZachary Turner     EXPECT_TRUE(PythonInteger::Check(chk_value1.get()));
40518426935SZachary Turner     EXPECT_TRUE(PythonString::Check(chk_value2.get()));
40618426935SZachary Turner 
40718426935SZachary Turner     PythonInteger chk_int(PyRefType::Borrowed, chk_value1.get());
40818426935SZachary Turner     PythonString chk_str(PyRefType::Borrowed, chk_value2.get());
40918426935SZachary Turner 
41018426935SZachary Turner     EXPECT_EQ(value_0, chk_int.GetInteger());
41118426935SZachary Turner     EXPECT_STREQ(value_1, chk_str.GetString().str().c_str());
41222c8efcdSZachary Turner }
41322c8efcdSZachary Turner 
41418426935SZachary Turner TEST_F(PythonDataObjectsTest, TestPythonDictionaryToStructuredDictionary)
41522c8efcdSZachary Turner {
41618426935SZachary Turner     static const char *const string_key0 = "String Key 0";
41718426935SZachary Turner     static const char *const string_key1 = "String Key 1";
41822c8efcdSZachary Turner 
41918426935SZachary Turner     static const char *const string_value0 = "String Value 0";
42018426935SZachary Turner     static const long int_value1 = 7;
42122c8efcdSZachary Turner 
422f8b22f8fSZachary Turner     PythonDictionary dict(PyInitialValue::Empty);
42318426935SZachary Turner     dict.SetItemForKey(PythonString(string_key0), PythonString(string_value0));
42418426935SZachary Turner     dict.SetItemForKey(PythonString(string_key1), PythonInteger(int_value1));
42522c8efcdSZachary Turner 
42618426935SZachary Turner     auto dict_sp = dict.CreateStructuredDictionary();
42718426935SZachary Turner     EXPECT_EQ(2, dict_sp->GetSize());
42822c8efcdSZachary Turner 
42918426935SZachary Turner     EXPECT_TRUE(dict_sp->HasKey(string_key0));
43018426935SZachary Turner     EXPECT_TRUE(dict_sp->HasKey(string_key1));
43122c8efcdSZachary Turner 
43218426935SZachary Turner     auto string_sp = dict_sp->GetValueForKey(string_key0)->GetAsString();
43318426935SZachary Turner     auto int_sp = dict_sp->GetValueForKey(string_key1)->GetAsInteger();
43422c8efcdSZachary Turner 
43518426935SZachary Turner     EXPECT_STREQ(string_value0, string_sp->GetValue().c_str());
43618426935SZachary Turner     EXPECT_EQ(int_value1, int_sp->GetValue());
43722c8efcdSZachary Turner }
4389c40264fSZachary Turner 
4399c40264fSZachary Turner TEST_F(PythonDataObjectsTest, TestPythonFile)
4409c40264fSZachary Turner {
4419c40264fSZachary Turner     File file(FileSystem::DEV_NULL, File::eOpenOptionRead);
4429c40264fSZachary Turner     PythonFile py_file(file, "r");
4439c40264fSZachary Turner     EXPECT_TRUE(PythonFile::Check(py_file.get()));
4449c40264fSZachary Turner }
4457d6d218eSZachary Turner 
4467d6d218eSZachary Turner TEST_F(PythonDataObjectsTest, TestObjectAttributes)
4477d6d218eSZachary Turner {
4487d6d218eSZachary Turner     PythonInteger py_int(42);
4497d6d218eSZachary Turner     EXPECT_TRUE(py_int.HasAttribute("numerator"));
4507d6d218eSZachary Turner     EXPECT_FALSE(py_int.HasAttribute("this_should_not_exist"));
4517d6d218eSZachary Turner 
4527d6d218eSZachary Turner     PythonInteger numerator_attr = py_int.GetAttributeValue("numerator").AsType<PythonInteger>();
4537d6d218eSZachary Turner     EXPECT_TRUE(numerator_attr.IsAllocated());
4547d6d218eSZachary Turner     EXPECT_EQ(42, numerator_attr.GetInteger());
4557d6d218eSZachary Turner }