Skip to content

Commit ef17067

Browse files
Barnabás Domozibarnabasdomozi
authored andcommitted
[PythonTest] Service test - node properties, reference tests
1 parent 9354070 commit ef17067

File tree

2 files changed

+300
-11
lines changed

2 files changed

+300
-11
lines changed

plugins/python/test/sources/classes.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,9 @@ def __init__(self) -> None:
2323
class Derived2(Derived, Base):
2424
def __init__(self) -> None:
2525
pass
26+
27+
base = Base()
28+
29+
def func():
30+
class A:
31+
z = 2

plugins/python/test/src/pythonservicetest.cpp

Lines changed: 294 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <model/file.h>
77
#include <model/file-odb.hxx>
8+
#include <model/position.h>
89

910
using namespace cc;
1011
using namespace cc::service::language;
@@ -22,42 +23,324 @@ class PythonServiceTest : public ::testing::Test
2223
webserver::ServerContext(std::string(), boost::program_options::variables_map()))
2324
)
2425
{
25-
}
26-
27-
model::File queryFile(const std::string& filename)
28-
{
29-
return _transaction([&, this]() {
30-
return _db->query_value<model::File>(odb::query<model::File>::filename == filename);
31-
});
26+
loadFile("functions.py");
27+
loadFile("classes.py");
28+
loadFile("imports.py");
3229
}
3330

3431
AstNodeInfo getAstNodeInfoByPosition(const std::string& filename, int32_t line, int32_t column)
3532
{
36-
model::File file = queryFile(filename);
33+
AstNodeInfo nodeInfo;
34+
35+
if (m_files.count(filename) == 0)
36+
{
37+
return nodeInfo;
38+
}
39+
40+
model::FileId file_id = m_files[filename];
3741

3842
service::core::FilePosition filePos;
39-
filePos.file = std::to_string(file.id);
43+
filePos.file = std::to_string(file_id);
4044
filePos.pos.line = line;
4145
filePos.pos.column = column;
4246

43-
AstNodeInfo nodeInfo;
4447
_pythonservice->getAstNodeInfoByPosition(nodeInfo, filePos);
4548
return nodeInfo;
4649
}
4750

51+
size_t referenceFinder(const std::vector<AstNodeInfo>& references,
52+
const std::vector<model::Position>& positions)
53+
{
54+
size_t c = 0;
55+
for (const AstNodeInfo& info : references)
56+
{
57+
size_t line = info.range.range.startpos.line;
58+
size_t column = info.range.range.startpos.column;
59+
60+
for (const model::Position& pos : positions)
61+
{
62+
if (pos.line == line && pos.column == column) c++;
63+
}
64+
}
65+
66+
return c;
67+
}
68+
4869
private:
4970
std::shared_ptr<odb::database> _db;
5071
util::OdbTransaction _transaction;
72+
std::unordered_map<std::string, std::uint64_t> m_files;
73+
void loadFile(const std::string& filename)
74+
{
75+
_transaction([&, this]() {
76+
model::File file = _db->query_value<model::File>(odb::query<model::File>::filename == filename);
77+
m_files.emplace(filename, file.id);
78+
});
79+
}
5180

5281
protected:
5382
std::shared_ptr<PythonServiceHandler> _pythonservice;
5483
};
5584

5685
TEST_F(PythonServiceTest, AstNodeInfoByPosition)
5786
{
87+
AstNodeInfo nodeInfo;
88+
5889
// Simulating click on line 1 column 5
59-
AstNodeInfo nodeInfo = getAstNodeInfoByPosition("functions.py", 1, 5);
90+
nodeInfo = getAstNodeInfoByPosition("functions.py", 1, 5);
6091

6192
EXPECT_EQ(nodeInfo.astNodeValue, "def hello_world()");
6293
EXPECT_EQ(nodeInfo.symbolType, "function");
94+
95+
nodeInfo = getAstNodeInfoByPosition("functions.py", 14, 12);
96+
97+
EXPECT_EQ(nodeInfo.astNodeValue, "mul");
98+
EXPECT_EQ(nodeInfo.symbolType, "statement");
99+
100+
nodeInfo = getAstNodeInfoByPosition("functions.py", 24, 10);
101+
102+
EXPECT_EQ(nodeInfo.astNodeValue, "MyLib");
103+
EXPECT_EQ(nodeInfo.symbolType, "statement");
104+
}
105+
106+
TEST_F(PythonServiceTest, NodeProperties)
107+
{
108+
AstNodeInfo nodeInfo;
109+
110+
nodeInfo = getAstNodeInfoByPosition("functions.py", 7, 5);
111+
std::map<std::string, std::string> map;
112+
113+
_pythonservice->getProperties(map, nodeInfo.id);
114+
EXPECT_EQ(nodeInfo.astNodeValue, "def mul(a, b)");
115+
116+
EXPECT_EQ(map.count("Full name"), 1);
117+
EXPECT_EQ(map["Full name"], "functions.mul");
118+
EXPECT_EQ(map.count("Builtin"), 1);
119+
EXPECT_EQ(map["Builtin"], "false");
120+
EXPECT_EQ(map.count("Function call"), 1);
121+
EXPECT_EQ(map["Function call"], "false");
122+
}
123+
124+
TEST_F(PythonServiceTest, NodePropertiesBuiltinCall)
125+
{
126+
AstNodeInfo nodeInfo;
127+
128+
nodeInfo = getAstNodeInfoByPosition("imports.py", 12, 17);
129+
EXPECT_EQ(nodeInfo.astNodeValue, "getpid");
130+
131+
std::map<std::string, std::string> map;
132+
133+
_pythonservice->getProperties(map, nodeInfo.id);
134+
EXPECT_EQ(map.count("Full name"), 1);
135+
EXPECT_EQ(map["Full name"], "imports.getpid");
136+
EXPECT_EQ(map.count("Builtin"), 1);
137+
EXPECT_EQ(map["Builtin"], "true");
138+
EXPECT_EQ(map.count("Function call"), 1);
139+
EXPECT_EQ(map["Function call"], "true");
140+
}
141+
142+
TEST_F(PythonServiceTest, NodeDefinition)
143+
{
144+
AstNodeInfo nodeInfo;
145+
std::vector<AstNodeInfo> references;
146+
147+
nodeInfo = getAstNodeInfoByPosition("functions.py", 11, 12);
148+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::DEFINITION, {});
149+
150+
EXPECT_EQ(references.size(), 1);
151+
EXPECT_EQ(references[0].symbolType, "function");
152+
EXPECT_EQ(references[0].astNodeValue, "def mul(a, b)");
153+
154+
references = {};
155+
nodeInfo = getAstNodeInfoByPosition("functions.py", 29, 6);
156+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::DEFINITION, {});
157+
158+
EXPECT_EQ(references.size(), 1);
159+
EXPECT_EQ(references[0].symbolType, "statement");
160+
EXPECT_EQ(references[0].astNodeValue, "mylib = {\n");
161+
162+
references = {};
163+
nodeInfo = getAstNodeInfoByPosition("classes.py", 27, 8);
164+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::DEFINITION, {});
165+
166+
EXPECT_EQ(references.size(), 1);
167+
EXPECT_EQ(references[0].symbolType, "class");
168+
EXPECT_EQ(references[0].astNodeValue, "class Base:\n");
169+
}
170+
171+
TEST_F(PythonServiceTest, NodeUsage)
172+
{
173+
AstNodeInfo nodeInfo;
174+
std::vector<AstNodeInfo> references;
175+
176+
nodeInfo = getAstNodeInfoByPosition("functions.py", 16, 1);
177+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::USAGE, {});
178+
179+
EXPECT_EQ(nodeInfo.astNodeValue, "mylib = {\n");
180+
EXPECT_EQ(references.size(), 2);
181+
182+
size_t found = referenceFinder(references, {{29, 6}, {46, 11}});
183+
EXPECT_EQ(found, references.size());
184+
}
185+
186+
TEST_F(PythonServiceTest, NodeDataMembers)
187+
{
188+
AstNodeInfo nodeInfo;
189+
std::vector<AstNodeInfo> references;
190+
191+
nodeInfo = getAstNodeInfoByPosition("classes.py", 1, 1);
192+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::DATA_MEMBER, {});
193+
194+
EXPECT_EQ(nodeInfo.astNodeValue, "class Base:\n");
195+
EXPECT_EQ(references.size(), 2);
196+
197+
size_t found = referenceFinder(references, {{2, 5}, {3, 5}});
198+
EXPECT_EQ(found, references.size());
199+
}
200+
201+
TEST_F(PythonServiceTest, NodeLocalVariables)
202+
{
203+
AstNodeInfo nodeInfo;
204+
std::vector<AstNodeInfo> references;
205+
206+
nodeInfo = getAstNodeInfoByPosition("functions.py", 96, 1);
207+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::LOCAL_VAR, {});
208+
209+
EXPECT_EQ(nodeInfo.astNodeValue, "def local_var()");
210+
EXPECT_EQ(references.size(), 3);
211+
212+
size_t found = referenceFinder(references, {{97, 5}, {98, 5}, {99, 9}});
213+
EXPECT_EQ(found, references.size());
214+
}
215+
216+
TEST_F(PythonServiceTest, NodeParent)
217+
{
218+
AstNodeInfo nodeInfo;
219+
std::vector<AstNodeInfo> references;
220+
221+
nodeInfo = getAstNodeInfoByPosition("functions.py", 97, 5);
222+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::PARENT, {});
223+
224+
EXPECT_EQ(nodeInfo.astNodeValue, "a = 2");
225+
EXPECT_EQ(references.size(), 1);
226+
227+
size_t found = referenceFinder(references, {{96, 1}});
228+
EXPECT_EQ(found, references.size());
229+
}
230+
231+
TEST_F(PythonServiceTest, NodeParentFunction)
232+
{
233+
AstNodeInfo nodeInfo;
234+
std::vector<AstNodeInfo> references;
235+
236+
nodeInfo = getAstNodeInfoByPosition("classes.py", 31, 9);
237+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::PARENT_FUNCTION, {});
238+
239+
EXPECT_EQ(nodeInfo.astNodeValue, "z = 2");
240+
EXPECT_EQ(references.size(), 1);
241+
242+
size_t found = referenceFinder(references, {{29, 1}});
243+
EXPECT_EQ(found, references.size());
244+
}
245+
246+
TEST_F(PythonServiceTest, NodeCaller)
247+
{
248+
AstNodeInfo nodeInfo;
249+
std::vector<AstNodeInfo> references;
250+
251+
nodeInfo = getAstNodeInfoByPosition("functions.py", 13, 1);
252+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::CALLER, {});
253+
254+
EXPECT_EQ(nodeInfo.astNodeValue, "def mul3()");
255+
EXPECT_EQ(references.size(), 2);
256+
257+
size_t found = referenceFinder(references, {{28, 6}, {45, 11}});
258+
EXPECT_EQ(found, references.size());
259+
}
260+
261+
TEST_F(PythonServiceTest, NodeThisCalls)
262+
{
263+
AstNodeInfo nodeInfo;
264+
std::vector<AstNodeInfo> references;
265+
266+
nodeInfo = getAstNodeInfoByPosition("functions.py", 10, 1);
267+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::THIS_CALLS, {});
268+
269+
EXPECT_EQ(nodeInfo.astNodeValue, "def mul2(a, b)");
270+
EXPECT_EQ(references.size(), 1);
271+
272+
size_t found = referenceFinder(references, {{11, 12}});
273+
EXPECT_EQ(found, references.size());
274+
}
275+
276+
TEST_F(PythonServiceTest, NodeMethod)
277+
{
278+
AstNodeInfo nodeInfo;
279+
std::vector<AstNodeInfo> references;
280+
281+
nodeInfo = getAstNodeInfoByPosition("classes.py", 1, 1);
282+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::METHOD, {});
283+
284+
EXPECT_EQ(nodeInfo.astNodeValue, "class Base:\n");
285+
EXPECT_EQ(references.size(), 3);
286+
287+
size_t found = referenceFinder(references, {{5, 5}, {8, 5}, {11, 5}});
288+
EXPECT_EQ(found, references.size());
289+
}
290+
291+
TEST_F(PythonServiceTest, NodeBaseClass)
292+
{
293+
AstNodeInfo nodeInfo;
294+
std::vector<AstNodeInfo> references;
295+
296+
nodeInfo = getAstNodeInfoByPosition("classes.py", 19, 1);
297+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::BASE_CLASS, {});
298+
299+
EXPECT_EQ(nodeInfo.astNodeValue, "class Derived(Base):\n");
300+
EXPECT_EQ(references.size(), 1);
301+
302+
size_t found = referenceFinder(references, {{1, 1}});
303+
EXPECT_EQ(found, references.size());
304+
305+
// ----------
306+
307+
references = {};
308+
nodeInfo = getAstNodeInfoByPosition("classes.py", 23, 1);
309+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::BASE_CLASS, {});
310+
311+
EXPECT_EQ(nodeInfo.astNodeValue, "class Derived2(Derived, Base):\n");
312+
EXPECT_EQ(references.size(), 2);
313+
314+
found = referenceFinder(references, {{1, 1}, {19, 1}});
315+
EXPECT_EQ(found, references.size());
316+
}
317+
318+
TEST_F(PythonServiceTest, NodeFunctionParam)
319+
{
320+
AstNodeInfo nodeInfo;
321+
std::vector<AstNodeInfo> references;
322+
323+
nodeInfo = getAstNodeInfoByPosition("functions.py", 4, 1);
324+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::PARAMETER, {});
325+
326+
EXPECT_EQ(nodeInfo.astNodeValue, "def runner(func, param1, param2)");
327+
EXPECT_EQ(references.size(), 3);
328+
329+
size_t found = referenceFinder(references, {{4, 12}, {4, 18}, {4, 26}});
330+
EXPECT_EQ(found, references.size());
331+
}
332+
333+
TEST_F(PythonServiceTest, NodeAnnotation)
334+
{
335+
AstNodeInfo nodeInfo;
336+
std::vector<AstNodeInfo> references;
337+
338+
nodeInfo = getAstNodeInfoByPosition("functions.py", 69, 1);
339+
_pythonservice->getReferences(references, nodeInfo.id, PythonServiceHandler::ANNOTATION, {});
340+
341+
EXPECT_EQ(nodeInfo.astNodeValue, "def annotation(a, b) -> None");
342+
EXPECT_EQ(references.size(), 1);
343+
344+
size_t found = referenceFinder(references, {{69, 24}});
345+
EXPECT_EQ(found, references.size());
63346
}

0 commit comments

Comments
 (0)