Salome HOME
f038e1d7a8a438744336052a75ceafcb61a57499
[tools/adao_interface.git] / TestAdaoExchange.cxx
1 // Copyright (C) 2019 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.
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 // Author: Anthony Geay, anthony.geay@edf.fr, EDF R&D
20
21 #include "TestAdaoExchange.hxx"
22
23 #include "AdaoExchangeLayer4Quintet.hxx"
24 #include "AdaoExchangeLayerException.hxx"
25 #include "AdaoModelKeyVal.hxx"
26 #include "PyObjectRAII.hxx"
27
28 #include "py2cpp/py2cpp.hxx"
29
30 #include <vector>
31 #include <iterator>
32
33 std::vector<double> func(const std::vector<double>& vec)
34 {
35   return {vec[0],2.*vec[1],3.*vec[2],vec[0]+2.*vec[1]+3.*vec[2]};
36 }
37
38 PyObject *multiFunc(PyObject *inp)
39 {
40   PyGILState_STATE gstate(PyGILState_Ensure());
41   PyObjectRAII iterator(PyObjectRAII::FromNew(PyObject_GetIter(inp)));
42   if(iterator.isNull())
43     throw AdaoExchangeLayerException("Input object is not iterable !");
44   PyObject *item(nullptr);
45   PyObjectRAII numpyModule(PyObjectRAII::FromNew(PyImport_ImportModule("numpy")));
46   if(numpyModule.isNull())
47     throw AdaoExchangeLayerException("Failed to load numpy");
48   PyObjectRAII ravelFunc(PyObjectRAII::FromNew(PyObject_GetAttrString(numpyModule,"ravel")));
49   std::vector< PyObjectRAII > pyrets;
50   while( item = PyIter_Next(iterator) )
51     {
52       PyObjectRAII item2(PyObjectRAII::FromNew(item));
53       {
54         PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(1)));
55         PyTuple_SetItem(args,0,item2.retn());
56         PyObjectRAII npyArray(PyObjectRAII::FromNew(PyObject_CallObject(ravelFunc,args)));
57         // Waiting management of npy arrays into py2cpp
58         PyObjectRAII lolistFunc(PyObjectRAII::FromNew(PyObject_GetAttrString(npyArray,"tolist")));
59         PyObjectRAII listPy;
60         {
61           PyObjectRAII args2(PyObjectRAII::FromNew(PyTuple_New(0)));
62           listPy=PyObjectRAII::FromNew(PyObject_CallObject(lolistFunc,args2));
63           }
64         std::vector<double> vect;
65         {
66           py2cpp::PyPtr listPy2(listPy.retn());
67           py2cpp::fromPyPtr(listPy2,vect);
68         }
69         //
70         PyGILState_Release(gstate);
71         std::vector<double> res(func(vect));
72         gstate=PyGILState_Ensure();
73         //
74         py2cpp::PyPtr resPy(py2cpp::toPyPtr(res));
75         PyObjectRAII resPy2(PyObjectRAII::FromBorrowed(resPy.get()));
76         pyrets.push_back(resPy2);
77       }
78     }
79   std::size_t len(pyrets.size());
80   PyObjectRAII ret(PyObjectRAII::FromNew(PyList_New(len)));
81   for(std::size_t i=0;i<len;++i)
82     {
83       PyList_SetItem(ret,i,pyrets[i].retn());
84     }
85   //PyObject *tmp(PyObject_Repr(ret));
86   // std::cerr << PyUnicode_AsUTF8(tmp) << std::endl;
87   PyGILState_Release(gstate);
88   return ret.retn();
89 }
90
91 PyObjectRAII NumpyToListWaitingForPy2CppManagement(PyObject *npObj)
92 {
93   PyObjectRAII func(PyObjectRAII::FromNew(PyObject_GetAttrString(npObj,"tolist")));
94   if(func.isNull())
95     throw AdaoExchangeLayerException("input pyobject does not have tolist attribute !");
96   PyObjectRAII args(PyObjectRAII::FromNew(PyTuple_New(0)));
97   PyObjectRAII ret(PyObjectRAII::FromNew(PyObject_CallObject(func,args)));
98   return ret;
99 }
100
101 void AdaoExchangeTest::setUp()
102 {
103 }
104
105 void AdaoExchangeTest::tearDown()
106 {
107 }
108
109 void AdaoExchangeTest::cleanUp()
110 {
111 }
112
113 using namespace AdaoModel;
114
115 void AdaoExchangeTest::test3DVar()
116 {
117   MainModel mm;
118   AdaoExchangeLayer4Quintet adao;
119   adao.init(&mm);
120   {
121     std::string sciptPyOfModelMaker(mm.pyStr());
122     std::cerr << sciptPyOfModelMaker << std::endl;
123   }
124   adao.execute();
125   PyObject *listOfElts( nullptr );
126   while( adao.next(listOfElts) )
127     {
128       PyObject *resultOfChunk(multiFunc(listOfElts));
129       adao.setResult(resultOfChunk);
130     }
131   PyObject *res(adao.getResult());
132   PyObjectRAII optimum(PyObjectRAII::FromNew(res));
133   PyObjectRAII optimum_4_py2cpp(NumpyToListWaitingForPy2CppManagement(optimum));
134   std::vector<double> vect;
135   {
136     py2cpp::PyPtr obj(optimum_4_py2cpp);
137     py2cpp::fromPyPtr(obj,vect);
138   }
139   CPPUNIT_ASSERT_EQUAL(3,(int)vect.size());
140   CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,vect[0],1e-7);
141   CPPUNIT_ASSERT_DOUBLES_EQUAL(3.,vect[1],1e-7);
142   CPPUNIT_ASSERT_DOUBLES_EQUAL(4.,vect[2],1e-7);
143 }
144
145 void AdaoExchangeTest::testBlue()
146 {
147   class TestBlueVisitor : public RecursiveVisitor
148   {
149   public:
150     void visit(GenericKeyVal *obj)
151     {
152       EnumAlgoKeyVal *objc(dynamic_cast<EnumAlgoKeyVal *>(obj));
153       if(objc)
154         objc->setVal(EnumAlgo::Blue);
155     }
156     void enterSubDir(DictKeyVal *subdir) { }
157     void exitSubDir(DictKeyVal *subdir) { }
158   };
159
160   MainModel mm;
161   //
162   TestBlueVisitor vis;
163   mm.visitAll(&vis);
164   //
165   AdaoExchangeLayer4Quintet adao;
166   adao.init(&mm);
167   {
168     std::string sciptPyOfModelMaker(mm.pyStr());
169     std::cerr << sciptPyOfModelMaker << std::endl;
170   }
171   adao.execute();
172     PyObject *listOfElts( nullptr );
173     while( adao.next(listOfElts) )
174       {
175         PyObject *resultOfChunk(multiFunc(listOfElts));
176         adao.setResult(resultOfChunk);
177       }
178     PyObject *res(adao.getResult());
179     PyObjectRAII optimum(PyObjectRAII::FromNew(res));
180     PyObjectRAII optimum_4_py2cpp(NumpyToListWaitingForPy2CppManagement(optimum));
181     std::vector<double> vect;
182     {
183       py2cpp::PyPtr obj(optimum_4_py2cpp);
184       py2cpp::fromPyPtr(obj,vect);
185     }
186     CPPUNIT_ASSERT_EQUAL(3,(int)vect.size());
187     CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,vect[0],1e-7);
188     CPPUNIT_ASSERT_DOUBLES_EQUAL(3.,vect[1],1e-7);
189     CPPUNIT_ASSERT_DOUBLES_EQUAL(4.,vect[2],1e-7);
190 }
191
192 void AdaoExchangeTest::testNonLinearLeastSquares()
193 {
194   class TestNonLinearLeastSquaresVisitor : public RecursiveVisitor
195   {
196   public:
197     void visit(GenericKeyVal *obj)
198     {
199       EnumAlgoKeyVal *objc(dynamic_cast<EnumAlgoKeyVal *>(obj));
200       if(objc)
201         objc->setVal(EnumAlgo::NonLinearLeastSquares);
202     }
203     void enterSubDir(DictKeyVal *subdir) { }
204     void exitSubDir(DictKeyVal *subdir) { }
205   };
206
207   MainModel mm;
208   //
209   TestNonLinearLeastSquaresVisitor vis;
210   mm.visitAll(&vis);
211   //
212   AdaoExchangeLayer4Quintet adao;
213   adao.init(&mm);
214   {
215     std::string sciptPyOfModelMaker(mm.pyStr());
216     std::cerr << sciptPyOfModelMaker << std::endl;
217   }
218   adao.execute();
219   PyObject *listOfElts( nullptr );
220   while( adao.next(listOfElts) )
221     {
222       PyObject *resultOfChunk(multiFunc(listOfElts));
223       adao.setResult(resultOfChunk);
224     }
225   PyObject *res(adao.getResult());
226   PyObjectRAII optimum(PyObjectRAII::FromNew(res));
227   PyObjectRAII optimum_4_py2cpp(NumpyToListWaitingForPy2CppManagement(optimum));
228   std::vector<double> vect;
229   {
230     py2cpp::PyPtr obj(optimum_4_py2cpp);
231     py2cpp::fromPyPtr(obj,vect);
232   }
233   CPPUNIT_ASSERT_EQUAL(3,(int)vect.size());
234   CPPUNIT_ASSERT_DOUBLES_EQUAL(2.,vect[0],1e-7);
235   CPPUNIT_ASSERT_DOUBLES_EQUAL(3.,vect[1],1e-7);
236   CPPUNIT_ASSERT_DOUBLES_EQUAL(4.,vect[2],1e-7);
237 }
238
239 CPPUNIT_TEST_SUITE_REGISTRATION( AdaoExchangeTest );
240
241 #include <cppunit/CompilerOutputter.h>
242 #include <cppunit/TestResult.h>
243 #include <cppunit/TestResultCollector.h>
244 #include <cppunit/TextTestProgressListener.h>
245 #include <cppunit/BriefTestProgressListener.h>
246 #include <cppunit/extensions/TestFactoryRegistry.h>
247 #include <cppunit/TestRunner.h>
248 #include <cppunit/TextTestRunner.h>
249
250 int main(int argc, char* argv[])
251 {
252   // --- Create the event manager and test controller
253   CPPUNIT_NS::TestResult controller;
254
255   // ---  Add a listener that collects test result
256   CPPUNIT_NS::TestResultCollector result;
257   controller.addListener( &result );        
258
259   // ---  Add a listener that print dots as test run.
260 #ifdef WIN32
261   CPPUNIT_NS::TextTestProgressListener progress;
262 #else
263   CPPUNIT_NS::BriefTestProgressListener progress;
264 #endif
265   controller.addListener( &progress );      
266
267   // ---  Get the top level suite from the registry
268
269   CPPUNIT_NS::Test *suite =
270     CPPUNIT_NS::TestFactoryRegistry::getRegistry().makeTest();
271
272   // ---  Adds the test to the list of test to run
273
274   CPPUNIT_NS::TestRunner runner;
275   runner.addTest( suite );
276   runner.run( controller);
277
278   // ---  Print test in a compiler compatible format.
279   std::ofstream testFile;
280   testFile.open("test.log", std::ios::out | std::ios::app);
281   testFile << "------ ADAO exchange test log:" << std::endl;
282   CPPUNIT_NS::CompilerOutputter outputter( &result, testFile );
283   outputter.write(); 
284
285   // ---  Run the tests.
286
287   bool wasSucessful = result.wasSuccessful();
288   testFile.close();
289
290   // ---  Return error code 1 if the one of test failed.
291
292   return wasSucessful ? 0 : 1;
293 }