Salome HOME
Join modifications from BR_Dev_For_4_0 tag V4_1_1.
[modules/med.git] / src / MEDMEM / Test / MEDMEMTest_Family.cxx
1 // Copyright (C) 2006  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
8 //
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20
21 #include "MEDMEMTest.hxx"
22 #include <cppunit/TestAssert.h>
23
24 #include "MEDMEM_define.hxx"
25 #include "MEDMEM_Family.hxx"
26 #include "MEDMEM_MedMeshDriver.hxx"
27 #include "MEDMEM_Mesh.hxx"
28 #include "MEDMEM_Support.hxx"
29 #include "MEDMEM_Compatibility21_22.hxx"
30
31 #include <sstream>
32 #include <cmath>
33
34 // use this define to enable lines, execution of which leads to Segmentation Fault
35 //#define ENABLE_FAULTS
36
37 // use this define to enable CPPUNIT asserts and fails, showing bugs
38 #define ENABLE_FORCED_FAILURES
39
40 using namespace std;
41 using namespace MEDMEM;
42
43 // #13: MEDMEM_Family.hxx  }  MEDMEMTest_Family.cxx
44
45 /*!
46  *  Check methods (24), defined in MEDMEM_Family.hxx:
47  *  class FAMILY : virtual public SUPPORT {
48  *   (+)     FAMILY();
49  *   (+)     FAMILY(MESH* Mesh, int Identifier, string Name,
50  *                  int NumberOfAttribute, int *AttributeIdentifier,
51  *                  int *AttributeValue, string AttributeDescription,
52  *                  int NumberOfGroup,   string GroupName,
53  *                  int * MEDArrayNodeFamily, int ** MEDArrayCellFamily,
54  *                  int ** MEDArrayFaceFamily, int ** MEDArrayEdgeFamily);
55  *   (+)     FAMILY(const FAMILY & m);
56  *   (+)     FAMILY(const SUPPORT & s);
57  *   (+)     virtual ~FAMILY();
58  *
59  *           // Does not work (Segmentation Fault of Hang up)
60  *   (!)     FAMILY & operator=(const FAMILY &fam);
61  *
62  *   (+)     friend ostream & operator<<(ostream &os, FAMILY &my);
63  *   (+)     friend ostream & operator<<(ostream &os, const FAMILY &my);
64  *
65  *   (+)     bool build(MED_EN::medEntityMesh Entity,int **FamilyNumber);
66  *
67  *   (+)     inline void setIdentifier             (int Identifier);
68  *   (+)     inline void setNumberOfAttributes     (int NumberOfAttribute);
69  *   (+)     inline void setAttributesIdentifiers  (int * AttributeIdentifier);
70  *   (+)     inline void setAttributesValues       (int * AttributeValue);
71  *   (+)     inline void setAttributesDescriptions (string * AttributeDescription);
72  *   (+)     inline void setNumberOfGroups         (int NumberOfGroups);
73  *   (+)     inline void setGroupsNames            (string * GroupName);
74  *
75  *   (+)     inline int            getIdentifier()             const;
76  *   (+)     inline int            getNumberOfAttributes()     const;
77  *   (+)     inline const int *    getAttributesIdentifiers()  const;
78  *   (+)     inline const int *    getAttributesValues()       const;
79  *   (+)     inline const string * getAttributesDescriptions() const;
80  *   (+)     inline int            getNumberOfGroups()         const;
81  *   (+)     inline const string * getGroupsNames()            const;
82  *
83  *   (+)     inline int    getAttributeIdentifier(int i)  const;
84  *   (+)     inline int    getAttributeValue(int i)       const;
85  *   (+)     inline string getAttributeDescription(int i) const;
86  *   (+)     inline string getGroupName(int i)            const;
87  *  }
88  *
89  *  Use code of MEDMEM/test_copie_family.cxx
90  */
91 void check_support(const SUPPORT * theSupport,
92                    string theName, string theDescr, MED_EN::medEntityMesh theEntity, int theNbTypes)
93 {
94   string aName  = theSupport->getName();
95   string aDescr = theSupport->getDescription();
96   MED_EN::medEntityMesh anEntity = theSupport->getEntity();
97   int aNbGeomTypes = theSupport->getNumberOfTypes();
98
99   CPPUNIT_ASSERT_EQUAL(theName, aName);
100   CPPUNIT_ASSERT_EQUAL(theDescr, aDescr);
101   CPPUNIT_ASSERT_EQUAL(theEntity, anEntity);
102   CPPUNIT_ASSERT_EQUAL(theNbTypes, aNbGeomTypes);
103
104   cout << "  - Entities list : " << endl;
105   if (!(theSupport->isOnAllElements())) {
106     cout << "  - NumberOfTypes : " << aNbGeomTypes << endl;
107     const MED_EN::medGeometryElement * Types = theSupport->getTypes();
108     for (int j = 0; j < aNbGeomTypes; j++) {
109       cout << "    * Type " << Types[j] << " : ";
110       int NumberOfElements = theSupport->getNumberOfElements(Types[j]);
111       const int * Number = theSupport->getNumber(Types[j]);
112       for (int k = 0; k < NumberOfElements; k++)
113         cout << Number[k] << " ";
114       cout << endl;
115     }
116   } else
117     cout << "    Is on all entities !" << endl;
118 }
119
120 void check_famille(const FAMILY * theFamily,
121                    string theName, string theDescr, MED_EN::medEntityMesh theEntity, int theNbTypes,
122                    int theID, int theNbAttributes, int theNbGroups)
123 {
124     check_support(theFamily, theName, theDescr, theEntity, theNbTypes);
125
126     // identifier
127     int id           = theFamily->getIdentifier();
128     int nbAttributes = theFamily->getNumberOfAttributes();
129     int nbGroups     = theFamily->getNumberOfGroups();
130
131     CPPUNIT_ASSERT_EQUAL(theID, id);
132     CPPUNIT_ASSERT_EQUAL(theNbAttributes, nbAttributes);
133     CPPUNIT_ASSERT_EQUAL(theNbGroups, nbGroups);
134
135     // attributes
136     cout << "  - Attributes (" << nbAttributes << ") :" << endl;
137     for (int j = 1; j < nbAttributes + 1; j++)
138       cout << "    * "
139            << theFamily->getAttributeIdentifier(j) << " : "
140            << theFamily->getAttributeValue(j) << ", "
141            << theFamily->getAttributeDescription(j).c_str() << endl;
142
143     // groups
144     cout << "  - Groups (" << nbGroups << ") :" << endl;
145     for (int j = 1; j < nbGroups + 1; j++)
146       cout << "    * " << theFamily->getGroupName(j).c_str() << endl;
147 }
148
149 void MEDMEMTest::testFamily()
150 {
151   ///////////////////////////////////
152   // TEST 1: test_copie_family.cxx //
153   ///////////////////////////////////
154   string datadir  = getenv("DATA_DIR");
155   string filename = datadir + "/MedFiles/pointe.med";
156   string meshname = "maa1";
157
158   MESH * aMesh = new MESH();
159   aMesh->setName(meshname);
160   MED_MESH_RDONLY_DRIVER aMeshDriver (filename, aMesh);
161   aMeshDriver.setMeshName(meshname);
162   aMeshDriver.open();
163   aMeshDriver.read();
164   aMeshDriver.close();
165
166   const FAMILY * aFamily1 = aMesh->getFamily(MED_EN::MED_NODE, 1);
167
168   // SUPPORT attributes
169   string aName     = aFamily1->getName();
170   string aDescr    = aFamily1->getDescription();
171   MED_EN::medEntityMesh anEntity = aFamily1->getEntity();
172   int aNbGeomTypes = aFamily1->getNumberOfTypes();
173
174   // FAMILY attributes
175   int id           = aFamily1->getIdentifier();
176   int nbAttributes = aFamily1->getNumberOfAttributes();
177   int nbGroups     = aFamily1->getNumberOfGroups();
178
179   // Dump
180   ostringstream ostr1;
181   ostr1 << *aFamily1;
182   CPPUNIT_ASSERT(ostr1.str() != "");
183
184   cout << "Show Family1 :" << endl;
185   check_famille(aFamily1,
186                 aName, aDescr, anEntity, aNbGeomTypes,
187                 id, nbAttributes, nbGroups);
188
189   // Copy constructor
190   FAMILY * aFamily2 = new FAMILY (* aFamily1);
191
192   // Dump
193   ostringstream ostr2;
194   ostr2 << *aFamily2;
195   CPPUNIT_ASSERT(ostr1.str() == ostr2.str());
196
197   // Compare supports
198   CPPUNIT_ASSERT(aFamily2->deepCompare(*aFamily1));
199
200   cout << "Show Family2 :" << endl;
201   check_famille(aFamily2,
202                 aName, aDescr, anEntity, aNbGeomTypes,
203                 id, nbAttributes, nbGroups);
204
205   // One more copy
206   FAMILY * aFamily3 = new FAMILY (* aFamily2);
207   delete aFamily2;
208
209   // Dump
210   ostringstream ostr3;
211   ostr3 << *aFamily3;
212   CPPUNIT_ASSERT(ostr1.str() == ostr3.str());
213
214   cout << "Show Family3 :" << endl;
215   check_famille(aFamily3,
216                 aName, aDescr, anEntity, aNbGeomTypes,
217                 id, nbAttributes, nbGroups);
218
219   cout << "That's all" << endl;
220
221   ////////////
222   // TEST 2 //
223   ////////////
224   {
225     // Prepare data
226
227     // attributes
228     int   newNumberOfAttribute = 3;
229     int * newAttributeIdentifier = new int[newNumberOfAttribute];
230     int * newAttributeValue = new int[newNumberOfAttribute];
231     string * newAttributeDescription = new string[newNumberOfAttribute];
232
233     char tmp [32];
234     for (int i = 0; i < newNumberOfAttribute; i++) {
235       newAttributeIdentifier[i] = i+1;
236       newAttributeValue[i] = (i+1)*10;
237       sprintf(tmp, "Attribut N° %d", i+1);
238       newAttributeDescription[i] = tmp;
239     }
240
241     // groups
242     int newNumberOfGroups = 4;
243     string * newGroups = new string[newNumberOfGroups];
244     for (int i = 0; i < newNumberOfGroups; i++) {
245       sprintf(tmp, "Group N° %d", i+1);
246       newGroups[i] = tmp;
247     }
248
249     // Change aFamily3
250
251     // attributes
252     aFamily3->setNumberOfAttributes(newNumberOfAttribute);
253     aFamily3->setAttributesIdentifiers(newAttributeIdentifier);
254     aFamily3->setAttributesValues(newAttributeValue);
255     aFamily3->setAttributesDescriptions(newAttributeDescription);
256
257     // groups
258     aFamily3->setNumberOfGroups(newNumberOfGroups);
259     aFamily3->setGroupsNames(newGroups, /*giveOwnership = */true);
260
261     // identifier
262     aFamily3->setIdentifier(77);
263
264     // check new parameters of aFamily3
265
266     // attributes
267     CPPUNIT_ASSERT_EQUAL(newNumberOfAttribute, aFamily3->getNumberOfAttributes());
268     const int *    newAttributeIdentifierBack  = aFamily3->getAttributesIdentifiers();
269     const int *    newAttributeValueBack       = aFamily3->getAttributesValues();
270     const string * newAttributeDescriptionBack = aFamily3->getAttributesDescriptions();
271     for (int i = 1; i <= newNumberOfAttribute; i++) {
272       sprintf(tmp, "Attribut N° %d", i);
273       string descr (tmp);
274
275       CPPUNIT_ASSERT_EQUAL(i    , aFamily3->getAttributeIdentifier(i));
276       CPPUNIT_ASSERT_EQUAL(i*10 , aFamily3->getAttributeValue(i));
277       CPPUNIT_ASSERT_EQUAL(descr, aFamily3->getAttributeDescription(i));
278
279       CPPUNIT_ASSERT_EQUAL(i    , newAttributeIdentifierBack[i - 1]);
280       CPPUNIT_ASSERT_EQUAL(i*10 , newAttributeValueBack[i - 1]);
281       CPPUNIT_ASSERT_EQUAL(descr, newAttributeDescriptionBack[i - 1]);
282     }
283
284     delete [] newAttributeIdentifier;
285     delete [] newAttributeValue;
286     delete [] newAttributeDescription;
287
288     // groups
289     CPPUNIT_ASSERT_EQUAL(newNumberOfGroups, aFamily3->getNumberOfGroups());
290     const string * newGroupsBack = aFamily3->getGroupsNames();
291     for (int i = 1; i <= newNumberOfGroups; i++) {
292       sprintf(tmp, "Group N° %d", i);
293       string grp (tmp);
294
295       CPPUNIT_ASSERT_EQUAL(grp, aFamily3->getGroupName(i));
296       CPPUNIT_ASSERT_EQUAL(grp, newGroupsBack[i - 1]);
297     }
298
299     // identifier
300     CPPUNIT_ASSERT_EQUAL(77, aFamily3->getIdentifier());
301   }
302
303   /////////////////////////////////////////////////////
304   // TEST 3: check default constructor and operator= //
305   /////////////////////////////////////////////////////
306   {
307     FAMILY aFamily4;
308 #ifdef ENABLE_FAULTS
309     aFamily4 = (const FAMILY &)*aFamily3;
310 #endif
311 #ifdef ENABLE_FORCED_FAILURES
312     // (BUG) Wrong implementation or usage of PointerOf<string>.
313     //       Do not use memcpy() with array of std::string!
314     CPPUNIT_FAIL("Impossible to use FAMILY::operator= because of"
315                  " wrong implementation or usage of PointerOf<string>");
316   /*{
317     int nb = 3;
318     string * str = new string[nb];
319
320     char tmp_str [32];
321     for (int i = 0; i < nb; i++) {
322       sprintf(tmp_str, "My String N° %d", i+1);
323       str[i] = tmp;
324     }
325
326     // bad
327     string* _pointer;
328     _pointer = new string[3];
329     // This is wrong, because class string is not simple type
330     // and can have pointers to some data, deallocated in it's destructor,
331     // which (data) will not be copied by this operation.
332     memcpy(_pointer, str, 3*sizeof(string));
333     delete [] _pointer;
334
335     // good
336     //PointerOf<int> p1 (1);
337     //PointerOf<int> p2 (20);
338     //p2 = newAttributeValue;
339     //p1.set(3, p2);
340
341     // bad
342     //PointerOf<string> p1 (1);
343     //PointerOf<string> p2 (20);
344     //p2 = str;
345     //p1.set(3, p2);
346
347     delete [] str;
348   }
349   */
350 #endif
351   }
352
353   ///////////////////////////////////////////////////
354   // TEST 4: check construction from given support //
355   ///////////////////////////////////////////////////
356   {
357     SUPPORT s1 (*aFamily3);
358     FAMILY  f1 (s1);
359     CPPUNIT_ASSERT_EQUAL(0, f1.getIdentifier());
360     CPPUNIT_ASSERT_EQUAL(0, f1.getNumberOfAttributes());
361     CPPUNIT_ASSERT_EQUAL(0, f1.getNumberOfGroups());
362     CPPUNIT_ASSERT(s1.deepCompare(f1));
363   }
364
365   delete aFamily3;
366   delete aMesh;
367
368   /////////////////////////////////////////////////////////////////
369   // TEST 5: check constructor, designed to use with med driver. //
370   /////////////////////////////////////////////////////////////////
371   {
372     MESH * aTestMesh = MEDMEMTest_createTestMesh();
373
374     // TestMesh families. Let's imagine that we would like to have
375     // the following nodes and elements distribution by families:
376
377     // NumberOfNodes = 19;
378     int aNodeFamily[19] = {1, 1, 1, 1, 1, 1, 1, 2, 2, 2,
379                            2, 2, 2, 2, 2, 2, 3, 3, 3};
380
381     // NumberOfCellTypes = 3;
382     // NumberOfCells[NumberOfCellTypes] = {12, 2, 2};
383     int aCellType1Family[12] = {4,4,4,4,4,5,5,5,5,5,5,5};
384     int aCellType2Family[ 2] = {5,6};
385     int aCellType3Family[ 2] = {6,6};
386     int * aCellFamily[3] = {aCellType1Family, aCellType2Family, aCellType3Family};
387
388     // NumberOfFaceTypes = 2;
389     // NumberOfFaces[NumberOfFaceTypes] = {4, 4};
390     int aFaceType1Family[4] = {7,7,7,7};
391     int aFaceType2Family[4] = {7,7,7,7};
392     int * aFaceFamily[3] = {aFaceType1Family, aFaceType2Family};
393
394     // No edges in aTestMesh
395     int ** anEdgeFamily = NULL;
396
397     // new families data
398     int attrId[2] = {1,2};
399     int attrVa[2] = {7,8};
400
401     string attrDescr1 ("Attribute 1 description");
402     string attrDescr2 ("Attribute 2 description");
403     string attrDescrEmpty (MED_TAILLE_DESC - 23, ' ');
404     attrDescr1 += attrDescrEmpty;
405     attrDescr2 += attrDescrEmpty;
406     CPPUNIT_ASSERT(MED_TAILLE_DESC == attrDescr1.length());
407     CPPUNIT_ASSERT(MED_TAILLE_DESC == attrDescr2.length());
408     string attrDescr = attrDescr1 + attrDescr2;
409
410     string groupName1 ("Group_1");
411     string groupName2 ("Group_2");
412     string groupName3 ("Group_3");
413     string groupNameEmpty (MED_TAILLE_LNOM - 7, ' ');
414     groupName1 += groupNameEmpty;
415     groupName2 += groupNameEmpty;
416     groupName3 += groupNameEmpty;
417     CPPUNIT_ASSERT(MED_TAILLE_LNOM == groupName1.length());
418     CPPUNIT_ASSERT(MED_TAILLE_LNOM == groupName2.length());
419     CPPUNIT_ASSERT(MED_TAILLE_LNOM == groupName3.length());
420     string groupNames = groupName1 + groupName2 + groupName3;
421
422     // nodes family 1
423     FAMILY aNodesF1 (aTestMesh, /*Identifier*/1, "Nodes 1", 
424                      /*NumberOfAttribute*/2, attrId, attrVa, attrDescr,
425                      /*NumberOfGroup*/3, groupNames,
426                      aNodeFamily, aCellFamily, aFaceFamily, anEdgeFamily);
427
428     //cout << "Show aNodesF1 :" << endl;
429     //cout << aNodesF1 << endl;
430
431     CPPUNIT_ASSERT_EQUAL(1, aNodesF1.getIdentifier());
432     CPPUNIT_ASSERT(strcmp("Nodes 1", aNodesF1.getName().c_str()) == 0);
433     CPPUNIT_ASSERT(MED_EN::MED_NODE == aNodesF1.getEntity());
434     CPPUNIT_ASSERT(!aNodesF1.isOnAllElements());
435     CPPUNIT_ASSERT_EQUAL(7, aNodesF1.getNumberOfElements(MED_EN::MED_ALL_ELEMENTS));
436
437     CPPUNIT_ASSERT_EQUAL(2, aNodesF1.getNumberOfAttributes());
438     CPPUNIT_ASSERT_EQUAL(1, aNodesF1.getAttributeIdentifier(1));
439     CPPUNIT_ASSERT_EQUAL(2, aNodesF1.getAttributeIdentifier(2));
440     CPPUNIT_ASSERT_EQUAL(7, aNodesF1.getAttributeValue(1));
441     CPPUNIT_ASSERT_EQUAL(8, aNodesF1.getAttributeValue(2));
442     CPPUNIT_ASSERT_EQUAL(attrDescr1, aNodesF1.getAttributeDescription(1));
443     CPPUNIT_ASSERT_EQUAL(attrDescr2, aNodesF1.getAttributeDescription(2));
444
445     CPPUNIT_ASSERT_EQUAL(3, aNodesF1.getNumberOfGroups());
446     CPPUNIT_ASSERT_EQUAL(groupName1, aNodesF1.getGroupName(1));
447     CPPUNIT_ASSERT_EQUAL(groupName2, aNodesF1.getGroupName(2));
448     CPPUNIT_ASSERT_EQUAL(groupName3, aNodesF1.getGroupName(3));
449
450     // faces family 7
451     FAMILY aFacesF7 (aTestMesh, /*Identifier*/7, "Faces All", 
452                      /*NumberOfAttribute*/2, attrId, attrVa, attrDescr,
453                      /*NumberOfGroup*/3, groupNames,
454                      aNodeFamily, aCellFamily, aFaceFamily, anEdgeFamily);
455
456     cout << "Show aFacesF7 :" << endl;
457     cout << aFacesF7 << endl;
458
459     CPPUNIT_ASSERT_EQUAL(7, aFacesF7.getIdentifier());
460     CPPUNIT_ASSERT(strcmp("Faces All", aFacesF7.getName().c_str()) == 0);
461     CPPUNIT_ASSERT(MED_EN::MED_FACE == aFacesF7.getEntity());
462
463     CPPUNIT_ASSERT_EQUAL(8, aTestMesh->getNumberOfElementsWithPoly(MED_EN::MED_FACE,
464                                                                    MED_EN::MED_ALL_ELEMENTS));
465     CPPUNIT_ASSERT_EQUAL(8, aFacesF7.getNumberOfElements(MED_EN::MED_ALL_ELEMENTS));
466
467 #ifdef ENABLE_FORCED_FAILURES
468     // ? (BUG) ? Why _isOnAllElts is set to true only for nodes and cells. What about faces?
469     //      _isOnAllElts = true ;
470     // See MEDMEM_Family.cxx lines 118-119 and 386-387.
471     CPPUNIT_ASSERT(aFacesF7.isOnAllElements());
472 #endif
473
474     CPPUNIT_ASSERT_EQUAL(2, aFacesF7.getNumberOfAttributes());
475     CPPUNIT_ASSERT_EQUAL(1, aFacesF7.getAttributeIdentifier(1));
476     CPPUNIT_ASSERT_EQUAL(2, aFacesF7.getAttributeIdentifier(2));
477     CPPUNIT_ASSERT_EQUAL(7, aFacesF7.getAttributeValue(1));
478     CPPUNIT_ASSERT_EQUAL(8, aFacesF7.getAttributeValue(2));
479     CPPUNIT_ASSERT_EQUAL(attrDescr1, aFacesF7.getAttributeDescription(1));
480     CPPUNIT_ASSERT_EQUAL(attrDescr2, aFacesF7.getAttributeDescription(2));
481
482     CPPUNIT_ASSERT_EQUAL(3, aFacesF7.getNumberOfGroups());
483     CPPUNIT_ASSERT_EQUAL(groupName1, aFacesF7.getGroupName(1));
484     CPPUNIT_ASSERT_EQUAL(groupName2, aFacesF7.getGroupName(2));
485     CPPUNIT_ASSERT_EQUAL(groupName3, aFacesF7.getGroupName(3));
486
487     delete aTestMesh;
488
489     // Method build() is not tested directly, but it is called from constructor, tested here
490   }
491 }