Salome HOME
[PY3] Convert py2yacs into Python3
[modules/yacs.git] / src / py2yacs / Test / Py2yacsTest.cxx
1 // Copyright (C) 2006-2016  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 #include <Python.h>
20 #include <fstream>
21 #include <string>
22 #include <sstream>
23
24 #include "Py2yacsTest.hxx"
25 #include "py2yacs.hxx"
26 #include "Proc.hxx"
27 #include "Executor.hxx"
28
29 #include "RuntimeSALOME.hxx"
30 #include "PythonPorts.hxx"
31 #include "InputPort.hxx"
32 //#include "parsers.hxx"
33
34 void Py2yacsTest::setUp()
35 {
36   YACS::ENGINE::RuntimeSALOME::setRuntime();
37   //YACS::ENGINE::getRuntime()->init();
38 }
39
40 void Py2yacsTest::tearDown()
41 {
42   //YACS::ENGINE::getRuntime()->fini();
43 }
44
45 static
46 void verifyCorrectPycode(const char * code_py, const char * function_name,
47                          int nbInputPorts, const char** input_ports,
48                          int nbOutputPorts, const char** output_ports)
49 {
50   std::cerr << std::endl;
51   std::cerr << "-----------------------------------------------" << std::endl;
52   std::cerr << code_py << std::endl;
53   std::cerr << "-----------------------------------------------" << std::endl;
54   std::cerr << "Function :" << function_name << std::endl;
55   Py2yacs parser;
56   try
57   {
58     parser.load(code_py);
59   }
60   catch(Py2yacsException& e)
61   {
62     CPPUNIT_FAIL(e.what());
63   }
64   catch(std::exception& e)
65   {
66     CPPUNIT_FAIL(e.what());
67   }
68   catch(...)
69   {
70     CPPUNIT_FAIL("Unknown exception");
71   }
72   YACS::ENGINE::Proc* p = parser.createProc(function_name);
73   CPPUNIT_ASSERT( p != NULL);
74   YACS::ENGINE::Node* n = p->getChildByShortName("default_name");
75   CPPUNIT_ASSERT( n != NULL);
76   CPPUNIT_ASSERT( n->getNumberOfInputPorts() == nbInputPorts);
77   for(int i = 0; i < nbInputPorts; i++)
78     CPPUNIT_ASSERT( n->getInputPort(input_ports[i]) != NULL);
79   CPPUNIT_ASSERT( n->getNumberOfOutputPorts() == nbOutputPorts);
80   for(int i = 0; i < nbOutputPorts; i++)
81     CPPUNIT_ASSERT( n->getOutputPort(output_ports[i]) != NULL);
82   delete p;
83 }
84
85 static
86 void verifyWrongPycode(const char* code_py, const char* function_name,
87                        const char* error_message)
88 {
89   Py2yacs parser;
90   try
91   {
92     parser.load(code_py);
93     YACS::ENGINE::Proc* p = parser.createProc(function_name);
94     CPPUNIT_FAIL("Exception expected and no exception occured.");
95   }
96   catch(Py2yacsException& e)
97   {
98     std::string what = e.what();
99     std::cerr << std::endl;
100     std::cerr << "-----------------------------------------------" << std::endl;
101     std::cerr << code_py << std::endl;
102     std::cerr << "-----------------------------------------------" << std::endl;
103     std::cerr << "Function :" << function_name << std::endl;
104     std::cerr << "==========EXCEPTION TEXT=======================" << std::endl;
105     std::cerr << what << std::endl;
106     std::cerr << "===============================================" << std::endl;
107     CPPUNIT_ASSERT(what.find(error_message) != std::string::npos);
108   }
109   catch(std::exception& e)
110   {
111     CPPUNIT_FAIL(e.what());
112   }
113 }
114
115 static
116 void verifyWrongParser(const char* parser_module, const char* parser_function,
117                        const char* error_message)
118 {
119   const char* code_py = "def f():\n"
120                         "  return\n";
121   Py2yacs parser(parser_module, parser_function);
122   try
123   {
124     parser.load(code_py);
125     CPPUNIT_FAIL("Exception expected and no exception occured.");
126   }
127   catch(Py2yacsException& e)
128   {
129     std::string what = e.what();
130     std::cerr << std::endl;
131     std::cerr << "==========EXCEPTION TEXT=======================" << std::endl;
132     std::cerr << what << std::endl;
133     std::cerr << "===============================================" << std::endl;
134     CPPUNIT_ASSERT(what.find(error_message) != std::string::npos);
135   }
136   catch(std::exception& e)
137   {
138     CPPUNIT_FAIL(e.what());
139   }
140 }
141
142 void Py2yacsTest::t1()
143 {
144   const char * code_py = "def f1(a, b, c):\n"
145                          "  y = a*b + c\n"
146                          "  return y\n";
147   const char* input_ports[] = {"a", "b", "c"};
148   const char* output_ports[] = {"y"};
149   verifyCorrectPycode(code_py, "f1", 3, input_ports, 1, output_ports);
150 }
151
152 void Py2yacsTest::t2()
153 {
154   const char * code_py = "def f1(a, b, c):\n"
155                          "  x = a + b + c\n"
156                          "  y = a*b + c\n"
157                          "  z = a*b*c\n"
158                          "  return x, y, z\n";
159   const char* input_ports[] = {"a", "b", "c"};
160   const char* output_ports[] = {"x", "y", "z"};
161   verifyCorrectPycode(code_py, "f1", 3, input_ports, 3, output_ports);
162 }
163
164 void Py2yacsTest::t3()
165 {
166   const char * code_py = "def f1(a, b, c):\n"
167                          "  print(a)\n"
168                          "  print(b)\n"
169                          "  print(c)\n";
170   const char* input_ports[] = {"a", "b", "c"};
171   const char* output_ports[] = {};
172   verifyCorrectPycode(code_py, "f1", 3, input_ports, 0, output_ports);
173 }
174
175 void Py2yacsTest::t4()
176 {
177   const char * code_py = "def f1():\n"
178                          "  print('toto')\n"
179                          "  return\n";
180   const char* input_ports[] = {"a", "b", "c"};
181   const char* output_ports[] = {};
182   verifyCorrectPycode(code_py, "f1", 0, input_ports, 0, output_ports);
183 }
184
185 void Py2yacsTest::t5()
186 {
187   const char * code_py = "def f1(a):\n"
188                          "  x = -a\n"
189                          "  if a > 0:\n"
190                          "    return a\n"
191                          "  else:\n"
192                          "    return x\n"
193                          "class ignoremoi:\n"
194                          "  def ignoreF(t):\n"
195                          "    return t+1\n"
196                          "def f2(v):\n"
197                          "  ret = f1(v)\n"
198                          "  return ret\n";
199   const char* input_ports[] = {"v"};
200   const char* output_ports[] = {"ret"};
201   verifyCorrectPycode(code_py, "f2", 1, input_ports, 1, output_ports);
202 }
203
204 void Py2yacsTest::no_multiple_returns()
205 {
206   const char * code_py = "def f(a):\n"
207                          "  x = -a\n"
208                          "  if a > 0:\n"
209                          "    return a\n"
210                          "  else:\n"
211                          "    return x\n";
212   verifyWrongPycode(code_py, "f", "multiple returns.");
213 }
214
215 void Py2yacsTest::unaccepted_statement()
216 {
217   const char * code_py = "def f(a):\n"
218                          "  return a\n"
219                          "x=5\n";
220   verifyWrongPycode(code_py, "f", "not accepted statement");
221 }
222
223 void Py2yacsTest::unaccepted_statement2()
224 {
225   const char * code_py = "def f(a):\n"
226                          "  return a\n"
227                          "if __name__ == '__main__':"
228                          "  print 'toto'\n";
229   verifyWrongPycode(code_py, "f", "not accepted statement");
230 }
231
232 void Py2yacsTest::unaccepted_return()
233 {
234   const char * code_py = "def f(a):\n"
235                          "  return 7\n";
236   verifyWrongPycode(code_py, "f", "invalid type returned");
237 }
238
239 void Py2yacsTest::unaccepted_return2()
240 {
241   const char * code_py = "def f1(a):\n"
242                          "  return 7\n"
243                          "def f2(x):\n"
244                          "  return f1(x)\n";
245   verifyWrongPycode(code_py, "f2", "invalid type returned");
246 }
247
248 void Py2yacsTest::syntaxError()
249 {
250   const char * code_py = "bla bla bla\n"
251                          "  return f1(x)\n";
252   verifyWrongPycode(code_py, "f2", "invalid syntax");
253 }
254
255 void Py2yacsTest::badFunctionName()
256 {
257   const char * code_py = "def f1(a):\n"
258                          "  x=7\n"
259                          "  return x\n"
260                          "def f2(x):\n"
261                          "  y=8\n"
262                          "  return y\n";
263   verifyWrongPycode(code_py, "nonexistant", "Function not found:");
264 }
265
266 void Py2yacsTest::schemaExec()
267 {
268   const char * code_py = "def f(a):\n"
269                          "  x = a\n"
270                          "  return x\n";
271   Py2yacs parser;
272   try
273   {
274     parser.load(code_py);
275   }
276   catch(Py2yacsException& e)
277   {
278     CPPUNIT_FAIL(e.what());
279   }
280   catch(...)
281   {
282     CPPUNIT_FAIL("Unknown exception");
283   }
284   YACS::ENGINE::Proc* p = parser.createProc("f");
285   CPPUNIT_ASSERT( p != NULL);
286   YACS::ENGINE::Node* n = p->getChildByShortName("default_name");
287   CPPUNIT_ASSERT( n != NULL);
288   CPPUNIT_ASSERT( n->getInputPort("a") != NULL);
289   CPPUNIT_ASSERT( n->getOutputPort("x") != NULL);
290   // run the schema
291   n->getInputPort("a")->edInit(42.);
292   YACS::ENGINE::Executor executor;
293   executor.RunW(p, 0);
294   // verify the output port value
295   YACS::ENGINE::OutputPyPort* var = dynamic_cast<YACS::ENGINE::OutputPyPort*>(n->getOutputPort("x"));
296   CPPUNIT_ASSERT(var);
297   PyObject* pyVal = var->get();
298   CPPUNIT_ASSERT(pyVal);
299   CPPUNIT_ASSERT(PyFloat_Check(pyVal));
300   CPPUNIT_ASSERT_DOUBLES_EQUAL(42., PyFloat_AsDouble(pyVal), 1.E-12);
301 }
302
303 // Test the behaviour when there is an error in the python parser
304 void Py2yacsTest::parserErrors()
305 {
306   verifyWrongParser("bad_parsers", "p1", "0 positional arguments");
307   verifyWrongParser("bad_parsers", "p2", "'str' object has no attribute 'name'");
308   verifyWrongParser("bad_parsers", "p3", "should be a python list");
309   verifyWrongParser("bad_parsers", "p4", "unsupported operand type");
310   verifyWrongParser("bad_parsers", "f", "Cannot find the parsing function");
311   verifyWrongParser("err_py2yacs_invalid", "get_properties", "invalid syntax");
312   verifyWrongParser("no_file", "f", "Failed to load");
313   verifyWrongParser("bad_parsers", "p5", "is not a string");
314   verifyWrongParser("bad_parsers", "p6", "is not a string");
315   verifyWrongParser("bad_parsers", "p7", "is not a string");
316   verifyWrongParser("bad_parsers", "p8", "Attribute 'name' should be a string.");
317   verifyWrongParser("bad_parsers", "p9", "Not a python list");
318   verifyWrongParser("bad_parsers", "p10", "is not a string");
319 }
320
321 void Py2yacsTest::globalVerification()
322 {
323   std::ifstream file_stream("exemple_py2yacs.py");
324   if(!file_stream)
325     return;
326
327   std::stringstream buffer;
328   buffer << file_stream.rdbuf();
329   Py2yacs parser;
330   parser.load(buffer.str());
331   std::list<FunctionProperties>::const_iterator it_fp;
332   const std::list<FunctionProperties>& functions = parser.getFunctionProperties();
333   for(it_fp=functions.begin();it_fp!=functions.end();it_fp++)
334   {
335     std::cerr << "Function :" << it_fp->_name << std::endl;
336     std::list<std::string>::const_iterator it;
337     std::cerr << "Input ports :" ;
338     for(it=it_fp->_input_ports.begin();it!=it_fp->_input_ports.end();it++)
339       std::cerr << *it << ",";
340     std::cerr << std::endl;
341     std::cerr << "Output ports :" ;
342     for(it=it_fp->_output_ports.begin();it!=it_fp->_output_ports.end();it++)
343       std::cerr << *it << ",";
344     std::cerr << std::endl;
345     std::cerr << "Imports :" ;
346     for(it=it_fp->_imports.begin();it!=it_fp->_imports.end();it++)
347       std::cerr << *it << ",";
348     std::cerr << std::endl;
349     std::cerr << "Errors :" ;
350     for(it=it_fp->_errors.begin();it!=it_fp->_errors.end();it++)
351       std::cerr << *it << std::endl;
352     std::cerr << std::endl;
353     std::cerr << "-----------------------------------------" << std::endl;
354   }
355
356 }