source: trunk/test/napi_test_cpp.cxx @ 1822

Revision 1792, 16.7 KB checked in by Freddie Akeroyd, 6 months ago (diff)

Fix constness of various functions. Refs #286

Line 
1#include <iostream>
2#include <string>
3#include <sstream>
4#include <cstring>
5#include <cstdlib>
6#include <cstdio>
7#include <vector>
8#include <map>
9#include "napiconfig.h"
10#include "NeXusFile.hpp"
11
12using std::cout;
13using std::endl;
14using std::map;
15using std::multimap;
16using std::string;
17using std::vector;
18
19static std::string relativePathOf(const std::string& filenamestr) {
20  char cwd[1024];
21
22  getcwd(cwd, sizeof(cwd));
23 
24  if ( filenamestr.compare(0, strlen(cwd), cwd) == 0 )
25  {
26      return filenamestr.substr(strlen(cwd)+1);  // +1 to skip trailing /
27  }
28  else
29  {
30      return filenamestr;
31  }
32}
33
34static int writeTest(const string& filename, NXaccess create_code) {
35  NeXus::File file(filename, create_code);
36  // create group
37  file.makeGroup("entry", "NXentry", true);
38  // group attributes
39  file.putAttr("hugo", "namenlos");
40  file.putAttr("cucumber", "passion");
41  // put string
42  file.writeData("ch_data", "NeXus_data");
43
44  // 2d array
45  vector<int> array_dims;
46  array_dims.push_back(5);
47  array_dims.push_back(4);
48  char c1_array[5][4] = {{'a', 'b', 'c' ,'d'}, {'e', 'f', 'g' ,'h'}, 
49                         {'i', 'j', 'k', 'l'}, {'m', 'n', 'o', 'p'},
50                         {'q', 'r', 's' , 't'}};
51  file.makeData("c1_data", NeXus::CHAR, array_dims, true);
52  file.putData(c1_array);
53  file.closeData();
54
55  // 1d uint8 array
56  vector<uint8_t> i1_array;
57  for (size_t i = 0; i < 4; i++) {
58    i1_array.push_back(static_cast<uint8_t>(i+1));
59  }
60  file.writeData("i1_data", i1_array);
61
62  // 1d int16 array
63  vector<int16_t> i2_array;
64  for (size_t i = 0; i < 4; i++) {
65    i2_array.push_back(1000*(i+1));
66  }
67  file.writeData("i2_data", i2_array);
68
69  // 1d int32 data
70  vector<int32_t> i4_array;
71  for (size_t i = 0; i < 4; i++) {
72    i4_array.push_back(1000000*(i+1));
73  }
74  file.writeData("i4_data", i4_array);
75
76  // 2d float data
77  vector<float> r4_array;
78  for (size_t i = 0; i < 5*4; i++) {
79    r4_array.push_back(static_cast<float>(i));
80  }
81  file.writeData("r4_data", r4_array, array_dims);
82
83  // 2d double data - slab test
84  vector<double> r8_array;
85  for (size_t i = 0; i < 5*4; i++) {
86    r8_array.push_back(static_cast<double>(i+20));
87  }
88  file.makeData("r8_data", NeXus::FLOAT64, array_dims, true);
89  vector<int> slab_start;
90  slab_start.push_back(4);
91  slab_start.push_back(0);
92  vector<int> slab_size;
93  slab_size.push_back(1);
94  slab_size.push_back(4);
95  file.putSlab(&(r8_array[16]), slab_start, slab_size);
96  slab_start[0] = 0;
97  slab_start[1] = 0;
98  slab_size[0]=4;
99  slab_size[1]=4;
100  file.putSlab(&(r8_array[0]), slab_start, slab_size);
101
102  // add some attributes
103  file.putAttr("ch_attribute", "NeXus");
104  file.putAttr("i4_attribute", 42);
105  file.putAttr("r4_attribute", 3.14159265);
106
107  // set up for creating a link
108  NXlink link = file.getDataID();
109  file.closeData();
110
111  // int64 tests
112  vector<int64_t> grossezahl;
113#if HAVE_LONG_LONG_INT
114  grossezahl.push_back(12);
115  grossezahl.push_back(555555555555LL);
116  grossezahl.push_back(23);
117  grossezahl.push_back(777777777777LL);
118#else
119  grossezahl.push_back(12);
120  grossezahl.push_back(555555);
121  grossezahl.push_back(23);
122  grossezahl.push_back(77777);
123#endif
124  if (create_code != NXACC_CREATE) {
125    file.writeData("grosszahl", grossezahl);
126  }
127
128  // create a new group inside this one
129  file.makeGroup("data", "NXdata", true);
130
131  // create a link
132  file.makeLink(link);
133
134  // compressed data
135  array_dims[0] = 100;
136  array_dims[1] = 20;
137  vector<int> comp_array;
138  for (int i = 0; i < array_dims[0]; i++) {
139    for (int j = 0; j < array_dims[1]; j++) {
140      comp_array.push_back(i);
141    }
142  }
143  vector<int> cdims;
144  cdims.push_back(20);
145  cdims.push_back(20);
146  file.writeCompData("comp_data", comp_array, array_dims, NeXus::LZW, cdims);
147
148  // ---------- Test write Extendible Data --------------------------
149  std::vector<int> data(10, 123);
150  file.makeGroup("extendible_data", "NXdata", 1);
151  file.writeExtendibleData("mydata1", data);
152  file.writeExtendibleData("mydata2", data, 1000);
153  std::vector<int64_t> dims(2);
154  dims[0] = 5;
155  dims[1] = 2;
156  std::vector<int64_t> chunk(2, 2);
157  file.writeExtendibleData("my2Ddata", data, dims, chunk);
158  file.putAttr("string_attrib", "some short string");
159
160  // Data vector can grow
161  for (size_t i=0; i<6; i++)
162    data.push_back(456);
163  data[0]=789;
164  file.writeUpdatedData("mydata1", data);
165
166  dims[0] = 8;
167  dims[1] = 2;
168  file.writeUpdatedData("my2Ddata", data, dims);
169
170  // Data vector can also shrink!
171  data.clear();
172  data.resize(5, 234);
173  file.writeUpdatedData("mydata2", data);
174
175  // Exit the group
176  file.closeGroup();
177  // ---------- End Test write Extendible Data --------------------------
178
179  // simple flush test
180  file.flush();
181
182  // real flush test
183  file.makeData("flush_data", NeXus::getType<int>(), NX_UNLIMITED, true);
184  vector<int> slab_array;
185  slab_array.push_back(0);
186  for (int i = 0 ; i < 7; i++) {
187    slab_array[0] = i;
188    file.putSlab(slab_array, i, 1);
189    file.flush();
190    file.openData("flush_data");
191  }
192  file.closeData();
193  file.closeGroup();
194
195  // create a sample
196  file.makeGroup("sample", "NXsample", true);
197  file.writeData("ch_data", "NeXus sample");
198
199  // make more links
200  NXlink glink = file.getGroupID();
201  file.openPath("/");
202  file.makeGroup("link", "NXentry", true);
203  file.makeLink(glink);
204  file.makeNamedLink("renLinkGroup", glink);
205  file.makeNamedLink("renLinkData", link);
206
207  return 0;
208}
209
210template <typename NumT>
211string toString(const vector<NumT> & data) {
212  std::stringstream result;
213  result << "[";
214  size_t size = data.size();
215  for (size_t i = 0; i < size; i++) {
216    result << data[i];
217    if (i+1 < size) {
218      result << ",";
219    }
220  }
221  result << "]";
222  return result.str();
223}
224
225int readTest(const string & filename) {
226  const string SDS("SDS");
227  // top level file information
228  NeXus::File file(filename);
229  cout << "NXinquirefile found: " << relativePathOf(file.inquireFile()) << endl;
230  vector<NeXus::AttrInfo> attr_infos = file.getAttrInfos();
231  cout << "Number of global attributes: " << attr_infos.size() << endl;
232  for (vector<NeXus::AttrInfo>::iterator it = attr_infos.begin();
233       it != attr_infos.end(); it++) {
234    if (it->name != "file_time" && it->name != "HDF_version" && it->name !=  "HDF5_Version" && it->name != "XML_version") {
235        cout << "   " << it->name << " = ";
236        if (it->type == NeXus::CHAR) {
237          cout << file.getStrAttr(*it);
238        }
239        cout << endl;
240    }
241  }
242
243  // check group attributes
244  file.openGroup("entry", "NXentry");
245  attr_infos = file.getAttrInfos();
246  cout << "Number of group attributes: " << attr_infos.size() << endl;
247  for (vector<NeXus::AttrInfo>::iterator it = attr_infos.begin();
248       it != attr_infos.end(); it++) {
249    cout << "   " << it->name << " = ";
250    if (it->type == NeXus::CHAR) {
251      cout << file.getStrAttr(*it);
252    }
253    cout << endl;
254  }
255
256  // print out the entry level fields
257  map<string, string> entries = file.getEntries();
258  cout << "Group contains " << entries.size() << " items" << endl;
259  NeXus::Info info;
260  for (map<string,string>::const_iterator it = entries.begin();
261       it != entries.end(); it++) {
262    cout << "   " << it->first;
263    if (it->second == SDS) {
264      file.openData(it->first);
265      info = file.getInfo();
266      cout << toString(info.dims) << " = ";
267      if (info.type == NeXus::CHAR) {
268        if (info.dims.size()==1) {
269          cout << file.getStrData();
270        }
271        else {
272          cout << "2d character array";
273        }
274      }
275      else if (info.type == NeXus::FLOAT32) {
276        vector<float> * result = file.getData<float>();
277        cout << toString(*result);
278        delete result;
279      }
280      else if (info.type == NeXus::FLOAT64) {
281        vector<double>  * result = file.getData<double>();
282        cout << toString(*result);
283        delete result;
284      }
285      else if (info.type == NeXus::INT8) {
286        vector<int8_t> result;
287        file.getData(result);
288        cout << toString(result);
289      }
290      else if (info.type == NeXus::UINT8) {
291        vector<uint8_t> result;
292        file.getData(result);
293        cout << toString(result);
294      }
295      else if (info.type == NeXus::INT16) {
296        vector<int16_t> result;
297        file.getData(result);
298        cout << toString(result);
299      }
300      else if (info.type == NeXus::UINT16) {
301        vector<uint16_t> result;
302        file.getData(result);
303        cout << toString(result);
304      }
305      else if (info.type == NeXus::INT32) {
306        vector<int32_t> result;
307        file.getData(result);
308        cout << toString(result);
309      }
310      else if (info.type == NeXus::UINT32) {
311        vector<uint32_t> result;
312        file.getData(result);
313        cout << toString(result);
314      }
315      else if (info.type == NeXus::INT64) {
316        vector<int64_t> result;
317        file.getData(result);
318        cout << toString(result);
319      }
320      else if (info.type == NeXus::UINT64) {
321        vector<uint64_t> result;
322        file.getData(result);
323        cout << toString(result);
324      }
325      cout <<  endl;
326      cout << "   Path = " << file.getPath() << endl;
327      file.closeData();
328    }
329    else {
330      cout << ":" << it->second << endl;
331    }
332  }
333
334        // Test getDataCoerce() -------------------
335        std::vector<int> ints;
336        std::vector<double> doubles;
337       
338        ints.clear();
339        file.openData("i1_data");
340        file.getDataCoerce(ints);
341        if (ints.size() != 4) return 1;
342        if (ints[0] != 1) return 1;
343        file.closeData();
344
345        ints.clear();
346        file.openData("i2_data");
347        file.getDataCoerce(ints);
348        if (ints.size() != 4) return 1;
349        if (ints[0] != 1000) return 1;
350        file.closeData();
351
352        ints.clear();
353        file.openData("i4_data");
354        file.getDataCoerce(ints);
355        if (ints.size() != 4) return 1;
356        if (ints[0] != 1000000) return 1;
357        file.closeData();
358
359        doubles.clear();
360        file.openData("r4_data");
361        file.getDataCoerce(doubles);
362        if (doubles.size() != 20) return 1;
363        if (doubles[1] != 1.0) return 1;
364        file.closeData();
365
366        doubles.clear();
367        file.openData("r8_data");
368        file.getDataCoerce(doubles);
369        if (doubles.size() != 20) return 1;
370        if (doubles[1] != 21.0) return 1;
371        file.closeData();
372
373        // Throws when you coerce to int from a real/double source
374        bool didThrow = false;
375        try 
376        {
377                ints.clear();
378                file.openData("r8_data");
379                file.getDataCoerce(ints);
380                file.closeData();
381                cout << "getDataCoerce(int) of doubles did not throw (it is supposed to throw)." << endl;
382        }
383        catch (...)
384        {
385                // Good! It is supposed to throw
386                didThrow = true;
387                file.closeData();
388        }
389        if (!didThrow) return 1;
390
391
392  // Close the "entry" group
393  file.closeGroup();
394
395  // check links
396  file.openGroup("entry", "NXentry");
397  file.openGroup("sample", "NXsample");
398  NXlink glink = file.getGroupID();
399  file.closeGroup();
400  file.openGroup("data", "NXdata");
401  file.openData("r8_data");
402  NXlink dlink = file.getDataID();
403  file.closeData();
404  file.closeGroup();
405  file.openData("r8_data");
406  NXlink d2link = file.getDataID();
407  file.closeData();
408  if (!file.sameID(dlink, d2link)) {
409    cout << "Link check FAILED (r8_data)" << endl;
410    cout << "     original data = ";
411    file.printLink(dlink);
412    cout << "     linked data = ";
413    file.printLink(d2link);
414    return 1;
415  }
416  file.closeGroup();
417
418  file.openGroup("link", "NXentry");
419  file.openGroup("sample", "NXsample");
420  NXlink g2link = file.getGroupID();
421  if (!file.sameID(glink, g2link)) {
422    cout << "Link check FAILED (sample)" << endl;
423    cout << "     original group = ";
424    file.printLink(glink);
425    cout << "     linked group = ";
426    file.printLink(g2link);
427    return 1;
428  }
429  file.closeGroup();
430
431  file.openGroup("renLinkGroup", "NXsample");
432  g2link = file.getGroupID();
433  file.closeGroup();
434  if (!file.sameID(glink, g2link)) {
435    cout << "Link check FAILED (renLinkGroup)" << endl;
436    cout << "     original group = ";
437    file.printLink(glink);
438    cout << "     linked group = ";
439    file.printLink(g2link);
440    return 1;
441  }
442
443  file.openData("renLinkData");
444  d2link = file.getDataID();
445  file.closeData();
446  if (!file.sameID(dlink, d2link)) {
447    cout << "Link check FAILED (renLinkData)" << endl;
448    cout << "     original data = ";
449    file.printLink(dlink);
450    cout << "     linked data = ";
451    file.printLink(d2link);
452    return 1;
453  }
454
455  file.closeGroup();
456  cout << "Link check OK" << endl;
457
458  // openpath checks
459  file.openPath("/entry/data/comp_data");
460  file.openPath("/entry/data/comp_data");
461  file.openPath("../r8_data");
462  printf("NXopenpath checks OK\n");
463
464  // everything went fine
465  return 0;
466}
467
468int testLoadPath(const string & filename) {
469  if(getenv("NX_LOAD_PATH") != NULL){
470    NeXus::File file(filename);
471    cout << "Success loading NeXus file from path" << endl;
472    // cout << file.inquireFile() << endl; // DEBUG print
473  }
474  return 0;
475}
476
477int testExternal(const string & fileext, NXaccess create_code){
478  string filename("nxext_cpp" + fileext);
479  string exturl1("nxfile://data/dmc01" + fileext+"#entry1");
480  string exturl2("nxfile://data/dmc02" + fileext+"#entry1");
481
482  // create the external link
483  NeXus::File fileout(filename, create_code);
484  fileout.linkExternal("entry1", "NXentry", exturl1);
485  fileout.linkExternal("entry2", "NXentry", exturl2);
486  fileout.close();
487
488  // read the file to make sure things worked
489  NeXus::File filein(filename);
490  filein.openPath("/entry1/start_time");
491  cout << "First file time: " << filein.getStrData() << endl;
492  cout << "NXinquirefile found: " << relativePathOf(filein.inquireFile()) << endl;
493  filein.openPath("/entry2/sample/sample_name");
494  cout << "Second file sample: " << filein.getStrData() << endl;
495  cout << "NXinquirefile found: " << relativePathOf(filein.inquireFile()) << endl;
496  filein.openPath("/entry2/start_time");
497  cout << "Second file time: " << filein.getStrData() << endl;
498  filein.openPath("/");
499  cout << "entry1 external URL = "
500       << filein.isExternalGroup("entry1", "NXentry") << endl;
501
502  return 0;
503}
504
505static int streamTest(const std::string& fname, NXaccess create_mode)
506{
507    using namespace NeXus;
508    using namespace NeXus::Stream;
509    std::vector<double> w;
510    std::vector<double> w1;
511    w.push_back(1.0);
512    double d, d1;
513    int i;
514    // create an entry and a data item
515    File nf(fname, create_mode);
516    nf << Group("entry1", "NXentry") << Data("dat1", w, "int_attr", 3);
517    nf.close();
518    File nf1(fname, NXACC_RDWR);
519    // add a double_attr to an existing setup
520    nf1 >> Group("entry1", "NXentry") >> Data("dat1") << Attr("double_attr", 6.0) << Close;
521    nf1.close();
522    // read back data items
523    File nf2(fname, NXACC_READ);
524    nf2 >> Group("entry1", "NXentry") >> Data("dat1", w1, "int_attr", i, "double_attr", d);
525    // alternative way to read d1
526    nf2 >> Data("dat1") >> Attr("double_attr", d1);
527    nf2.close();
528    if (i != 3 || w != w1 || d != 6.0 || d1 != 6.0)
529    {
530        return 1;
531    }
532    return 0;
533}
534
535int testTypeMap(const std::string &fname)
536{
537        NeXus::File file(fname);
538        multimap<string, string> *map = file.getTypeMap();
539        size_t mapsize = 25;
540        // HDF4 does not have int64 capability, so resulting map is one shorter than HDF5 and XML files
541        if (fname == string("napi_test_cpp.hdf")) {
542                if (map->size() != (mapsize - 1))
543                {
544                        cout << "TypeMap is incorrect" << endl;
545                        return 1;
546                }
547        }
548        else {
549                if (map->size() != mapsize)
550                {
551                        cout << "TypeMap is incorrect" << endl;
552                        return 1;
553                }
554        }
555
556        cout << "TypeMap is correct size" << endl;
557
558        return 0;
559}
560
561int main(int argc, char** argv)
562{
563  NXaccess nx_creation_code;
564  string filename;
565  string extfile_ext;
566  if(strstr(argv[0],"napi_test_cpp-hdf5") != NULL){
567    nx_creation_code = NXACC_CREATE5;
568    filename = "napi_test_cpp.h5";
569    extfile_ext = ".h5";
570  }else if(strstr(argv[0],"napi_test_cpp-xml-table") != NULL){
571    nx_creation_code = NXACC_CREATEXML | NXACC_TABLE;
572    filename = "napi_test_cpp-table.xml";
573    extfile_ext = "-table.xml";
574  }else if(strstr(argv[0],"napi_test_cpp-xml") != NULL){
575    nx_creation_code = NXACC_CREATEXML;
576    filename = "napi_test_cpp.xml";
577    extfile_ext = ".xml";
578  } else {
579    nx_creation_code = NXACC_CREATE;
580    filename = "napi_test_cpp.hdf";
581    extfile_ext = ".hdf";
582  }
583
584  int result;
585  result = writeTest(filename, nx_creation_code);
586  if (result) {
587    cout << "writeTest failed" << endl;
588    return result;
589  }
590  if ( (argc >= 2) && !strcmp(argv[1], "-q") )
591  {
592    return 0;   //
593  }
594
595  // try reading a file
596  result = readTest(filename);
597  if (result) {
598    cout << "readTest failed" << endl;
599    return result;
600  }
601
602  // try using the load path
603  result = testLoadPath("dmc01.hdf");
604  if (result) {
605    cout << "testLoadPath failed" << endl;
606    return result;
607  }
608
609  // try external linking
610  result = testExternal(extfile_ext, nx_creation_code);
611  if (result) {
612    cout << "testExternal failed" << endl;
613    return result;
614  }
615
616
617  // quick test of stream interface
618  std::string fname = string("stream_test") + extfile_ext;
619  result = streamTest(fname, nx_creation_code);
620  remove(fname.c_str());
621  if (result) {
622    cout << "streamTest failed" << endl;
623    return result;
624  }
625
626  // test of typemap generation
627  result = testTypeMap(filename);
628  if (result) {
629          cout << "testTypeMap failed" << endl;
630          return result;
631  }
632
633  // everything went ok
634  return 0;
635}
Note: See TracBrowser for help on using the repository browser.