text: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   * Copyright by The HDF Group.                                               *
   * Copyright by the Board of Trustees of the University of Illinois.         *
   * All rights reserved.                                                      *
   *                                                                           *
   * This file is part of HDF5.  The full HDF5 copyright notice, including     *
   * terms governing use, modification, and redistribution, is contained in    *
   * the COPYING file, which can be found at the root of the source code       *
   * distribution tree, or in https://www.hdfgroup.org/licenses.               *
   * If you do not have access to either file, you may request a copy from     *
   * help@hdfgroup.org.                                                        *
   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  
  /*****************************************************************************
     FILE
     tcompound.cpp - HDF5 C++ testing the compound data type functionality
  
   ***************************************************************************/
  #include <iostream>
  using std::cerr;
  using std::endl;
  
  #include <string>
  #include "H5Cpp.h" // C++ API header file
  using namespace H5;
  
  #include "h5test.h"
  #include "h5cpputil.h" // C++ utilility header file
  
  /* Number of elements in each test */
  #define NTESTELEM 100000
  
  typedef struct complex_t {
      double re;
      double im;
  } complex_t;
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_1
   *
   * Purpose      Tests various things about compound data types.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (using C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_1()
  {
      // Output message about test being performed
      SUBTEST("Compound Data Types");
      try {
          // Create an empty compound datatype
          CompType complex_type(sizeof(complex_t));
  
          // Add a couple of fields
          complex_type.insertMember("real", HOFFSET(complex_t, re), PredType::NATIVE_DOUBLE);
          complex_type.insertMember("imaginary", HOFFSET(complex_t, im), PredType::NATIVE_DOUBLE);
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  } // test_compound_1()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_2
   *
   * Purpose      Tests a compound type conversion where the source and
   *              destination are the same except for the order of the
   *              elements.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_2()
  {
      typedef struct {
          int a, b, c[4], d, e;
      } src_typ_t;
      typedef struct {
          int e, d, c[4], b, a;
      } dst_typ_t;
  
      src_typ_t *    s_ptr;
      dst_typ_t *    d_ptr;
      const int      nelmts = NTESTELEM;
      const hsize_t  four   = 4;
      int            i;
      unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
      ArrayType *    array_dt = NULL;
  
      // Output message about test being performed
      SUBTEST("Compound Element Reordering");
      try {
          // Sizes should be the same, but be careful just in case
          buf  = (unsigned char *)HDmalloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t)));
          bkg  = (unsigned char *)HDmalloc(nelmts * sizeof(dst_typ_t));
          orig = (unsigned char *)HDmalloc(nelmts * sizeof(src_typ_t));
          for (i = 0; i < nelmts; i++) {
              s_ptr       = ((src_typ_t *)orig) + i;
              s_ptr->a    = i * 8 + 0;
              s_ptr->b    = i * 8 + 1;
              s_ptr->c[0] = i * 8 + 2;
              s_ptr->c[1] = i * 8 + 3;
              s_ptr->c[2] = i * 8 + 4;
              s_ptr->c[3] = i * 8 + 5;
              s_ptr->d    = i * 8 + 6;
              s_ptr->e    = i * 8 + 7;
          }
          memcpy(buf, orig, nelmts * sizeof(src_typ_t));
  
          // Build hdf5 datatypes
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
  
          // Create an empty compound datatype
          CompType st(sizeof(src_typ_t));
          st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
          st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT);
          st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt);
          st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT);
          st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT);
          array_dt->close();
          delete array_dt;
  
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
  
          // Create an empty compound datatype
          CompType dt(sizeof(dst_typ_t));
          dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT);
          dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_INT);
          dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt);
          dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_INT);
          dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT);
          array_dt->close();
  
          // Perform the conversion
          st.convert(dt, (size_t)nelmts, buf, bkg);
  
          // Compare results
          for (i = 0; i < nelmts; i++) {
              s_ptr = ((src_typ_t *)orig) + i;
              d_ptr = ((dst_typ_t *)buf) + i;
              if (s_ptr->a != d_ptr->a || s_ptr->b != d_ptr->b || s_ptr->c[0] != d_ptr->c[0] ||
                  s_ptr->c[1] != d_ptr->c[1] || s_ptr->c[2] != d_ptr->c[2] || s_ptr->c[3] != d_ptr->c[3] ||
                  s_ptr->d != d_ptr->d || s_ptr->e != d_ptr->e) {
                  H5_FAILED();
                  cerr << "    i=" << i << endl;
                  cerr << "    src={a=" << s_ptr->a << ", b=" << s_ptr->b << "c=[" << s_ptr->c[0] << ","
                       << s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" << s_ptr->d
                       << ", e=" << s_ptr->e << "}" << endl;
                  cerr << "    dst={a=" << s_ptr->a << ", b=" << s_ptr->b << "c=[" << s_ptr->c[0] << ","
                       << s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" << s_ptr->d
                       << ", e=" << s_ptr->e << "}" << endl;
              }
          }
          // Release resources
          HDfree(buf);
          HDfree(bkg);
          HDfree(orig);
          s_ptr = NULL;
          d_ptr = NULL;
          st.close();
          dt.close();
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  
      if (array_dt)
          delete array_dt;
  } // test_compound_2()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_3
   *
   * Purpose      Tests compound conversions where the source and destination
   *              are the same except the destination is missing a couple
   *              members which appear in the source.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_3()
  {
      typedef struct {
          int a, b, c[4], d, e;
      } src_typ_t;
      typedef struct {
          int a, c[4], e;
      } dst_typ_t;
  
      src_typ_t *    s_ptr;
      dst_typ_t *    d_ptr;
      int            i;
      const int      nelmts = NTESTELEM;
      const hsize_t  four   = 4;
      unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
      ArrayType *    array_dt = NULL;
  
      // Output message about test being performed
      SUBTEST("Compound Datatype Subset Conversions");
      try {
          /* Initialize */
          buf  = (unsigned char *)HDmalloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t)));
          bkg  = (unsigned char *)HDmalloc(nelmts * sizeof(dst_typ_t));
          orig = (unsigned char *)HDmalloc(nelmts * sizeof(src_typ_t));
          for (i = 0; i < nelmts; i++) {
              s_ptr       = ((src_typ_t *)orig) + i;
              s_ptr->a    = i * 8 + 0;
              s_ptr->b    = i * 8 + 1;
              s_ptr->c[0] = i * 8 + 2;
              s_ptr->c[1] = i * 8 + 3;
              s_ptr->c[2] = i * 8 + 4;
              s_ptr->c[3] = i * 8 + 5;
              s_ptr->d    = i * 8 + 6;
              s_ptr->e    = i * 8 + 7;
          }
          memcpy(buf, orig, nelmts * sizeof(src_typ_t));
  
          /* Build hdf5 datatypes */
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
  
          // Create an empty compound datatype
          CompType st(sizeof(src_typ_t));
          st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
          st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT);
          st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt);
          st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT);
          st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT);
          array_dt->close();
          delete array_dt;
  
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
  
          // Create an empty compound datatype
          CompType dt(sizeof(dst_typ_t));
          dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT);
          dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt);
          dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT);
          array_dt->close();
  
          /* Perform the conversion */
          st.convert(dt, (size_t)nelmts, buf, bkg);
  
          /* Compare results */
          for (i = 0; i < nelmts; i++) {
              s_ptr = ((src_typ_t *)orig) + i;
              d_ptr = ((dst_typ_t *)buf) + i;
              if (s_ptr->a != d_ptr->a || s_ptr->c[0] != d_ptr->c[0] || s_ptr->c[1] != d_ptr->c[1] ||
                  s_ptr->c[2] != d_ptr->c[2] || s_ptr->c[3] != d_ptr->c[3] || s_ptr->e != d_ptr->e) {
                  H5_FAILED();
                  cerr << "    i=" << i << endl;
                  cerr << "    src={a=" << s_ptr->a << ", b=" << s_ptr->b << ", c=[" << s_ptr->c[0] << ","
                       << s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << "], d=" << s_ptr->d
                       << ", e=" << s_ptr->e << "}" << endl;
                  cerr << "    dst={a=" << d_ptr->a << ", c=[" << d_ptr->c[0] << "," << d_ptr->c[1] << ","
                       << d_ptr->c[2] << "," << d_ptr->c[3] << "], e=" << d_ptr->e << "}" << endl;
              } // if
          }     // for
  
          /* Release resources */
          HDfree(buf);
          HDfree(bkg);
          HDfree(orig);
          s_ptr = NULL;
          d_ptr = NULL;
          st.close();
          dt.close();
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  
      if (array_dt)
          delete array_dt;
  } // test_compound_3()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_4
   *
   * Purpose      Tests compound conversions when the destination has the same
   *              fields as the source but one or more of the fields are
   *              smaller.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_4()
  {
  
      typedef struct {
          int a, b, c[4], d, e;
      } src_typ_t;
  
      typedef struct {
          short b;
          int   a, c[4];
          short d;
          int   e;
      } dst_typ_t;
  
      src_typ_t *    s_ptr;
      dst_typ_t *    d_ptr;
      int            i;
      const int      nelmts = NTESTELEM;
      const hsize_t  four   = 4;
      unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
      ArrayType *    array_dt = NULL;
  
      // Output message about test being performed
      SUBTEST("Compound Element Shrinking & Reordering");
      try {
          /* Sizes should be the same, but be careful just in case */
          buf  = (unsigned char *)HDmalloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t)));
          bkg  = (unsigned char *)HDmalloc(nelmts * sizeof(dst_typ_t));
          orig = (unsigned char *)HDmalloc(nelmts * sizeof(src_typ_t));
          for (i = 0; i < nelmts; i++) {
              s_ptr       = ((src_typ_t *)orig) + i;
              s_ptr->a    = i * 8 + 0;
              s_ptr->b    = (i * 8 + 1) & 0x7fff;
              s_ptr->c[0] = i * 8 + 2;
              s_ptr->c[1] = i * 8 + 3;
              s_ptr->c[2] = i * 8 + 4;
              s_ptr->c[3] = i * 8 + 5;
              s_ptr->d    = (i * 8 + 6) & 0x7fff;
              s_ptr->e    = i * 8 + 7;
          }
          memcpy(buf, orig, nelmts * sizeof(src_typ_t));
  
          /* Build hdf5 datatypes */
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
  
          // Create an empty compound datatype
          CompType st(sizeof(src_typ_t));
          st.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
          st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_INT);
          st.insertMember("c", HOFFSET(src_typ_t, c), *array_dt);
          st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_INT);
          st.insertMember("e", HOFFSET(src_typ_t, e), PredType::NATIVE_INT);
          array_dt->close();
          delete array_dt;
  
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, &four);
  
          // Create an empty compound datatype
          CompType dt(sizeof(dst_typ_t));
          dt.insertMember("a", HOFFSET(dst_typ_t, a), PredType::NATIVE_INT);
          dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_SHORT);
          dt.insertMember("c", HOFFSET(dst_typ_t, c), *array_dt);
          dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_SHORT);
          dt.insertMember("e", HOFFSET(dst_typ_t, e), PredType::NATIVE_INT);
          array_dt->close();
  
          /* Perform the conversion */
          st.convert(dt, (size_t)nelmts, buf, bkg);
  
          /* Compare results */
          for (i = 0; i < nelmts; i++) {
              s_ptr = ((src_typ_t *)orig) + i;
              d_ptr = ((dst_typ_t *)buf) + i;
              if (s_ptr->a != d_ptr->a || s_ptr->b != d_ptr->b || s_ptr->c[0] != d_ptr->c[0] ||
                  s_ptr->c[1] != d_ptr->c[1] || s_ptr->c[2] != d_ptr->c[2] || s_ptr->c[3] != d_ptr->c[3] ||
                  s_ptr->d != d_ptr->d || s_ptr->e != d_ptr->e) {
                  H5_FAILED();
                  cerr << "    i=" << i << endl;
                  cerr << "    src={a=" << s_ptr->a << ", b=" << s_ptr->b << "c=[" << s_ptr->c[0] << ","
                       << s_ptr->c[1] << "," << s_ptr->c[2] << "," << s_ptr->c[3] << ", d=" << s_ptr->d
                       << ", e=" << s_ptr->e << "}" << endl;
                  cerr << "    dst={a=" << d_ptr->a << ", b=" << d_ptr->b << "c=[" << d_ptr->c[0] << ","
                       << d_ptr->c[1] << "," << d_ptr->c[2] << "," << d_ptr->c[3] << ", d=" << d_ptr->d
                       << ", e=" << d_ptr->e << "}" << endl;
              } // if
          }     // for
  
          /* Release resources */
          HDfree(buf);
          HDfree(bkg);
          HDfree(orig);
          s_ptr = NULL;
          d_ptr = NULL;
          st.close();
          dt.close();
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  
      if (array_dt)
          delete array_dt;
  } // test_compound_4()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_5
   *
   * Purpose      Many versions of HDF5 have a bug in the optimized compound
   *              datatype conversion function, H5T_conv_struct_opt(), which
   *              is triggered when the top-level type contains a struct
   *              which must undergo a conversion.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_5()
  {
      typedef struct {
          char  name[16];
          short tdim;
          short coll_ids[4];
      } src_typ_t;
  
      typedef struct {
          char  name[16];
          short tdim;
          int   coll_ids[4];
      } dst_typ_t;
  
      hsize_t    dims[1] = {4};
      src_typ_t  src[2]  = {{"one", 102, {104, 105, 106, 107}}, {"two", 202, {204, 205, 206, 207}}};
      dst_typ_t *dst;
      void *     buf      = HDcalloc(2, sizeof(dst_typ_t));
      void *     bkg      = HDcalloc(2, sizeof(dst_typ_t));
      ArrayType *array_dt = NULL;
  
      // Output message about test being performed
      SUBTEST("Optimized Struct Converter");
      try {
  
          /* Build datatypes */
          array_dt = new ArrayType(PredType::NATIVE_SHORT, 1, dims);
          CompType short_array(4 * sizeof(short));
          short_array.insertMember("_", 0, *array_dt);
          array_dt->close();
          delete array_dt;
  
          CompType int_array(4 * sizeof(int));
          array_dt = new ArrayType(PredType::NATIVE_INT, 1, dims);
          int_array.insertMember("_", 0, *array_dt);
          array_dt->close();
  
          StrType  strg(PredType::C_S1, 16);
          CompType src_type(sizeof(src_typ_t));
          src_type.insertMember("name", HOFFSET(src_typ_t, name), strg);
          src_type.insertMember("tdim", HOFFSET(src_typ_t, tdim), PredType::NATIVE_SHORT);
          src_type.insertMember("coll_ids", HOFFSET(src_typ_t, coll_ids), short_array);
  
          CompType dst_type(sizeof(dst_typ_t));
          dst_type.insertMember("name", HOFFSET(dst_typ_t, name), strg);
          dst_type.insertMember("tdim", HOFFSET(dst_typ_t, tdim), PredType::NATIVE_SHORT);
          dst_type.insertMember("coll_ids", HOFFSET(dst_typ_t, coll_ids), int_array);
  
          /* Convert data */
          memcpy(buf, src, sizeof(src));
          src_type.convert(dst_type, (size_t)2, buf, bkg);
          dst = (dst_typ_t *)buf;
  
          /* Cleanup */
          src_type.close();
          dst_type.close();
          strg.close();
          short_array.close();
          int_array.close();
  
          /* Check results */
          if (memcmp(src[1].name, dst[1].name, sizeof(src[1].name)) != 0 || src[1].tdim != dst[1].tdim ||
              src[1].coll_ids[0] != dst[1].coll_ids[0] || src[1].coll_ids[1] != dst[1].coll_ids[1] ||
              src[1].coll_ids[2] != dst[1].coll_ids[2] || src[1].coll_ids[3] != dst[1].coll_ids[3]) {
              H5_FAILED();
          }
  
          /* Free memory buffers */
          HDfree(buf);
          HDfree(bkg);
          dst = NULL;
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  
      if (array_dt)
          delete array_dt;
  } // test_compound_5()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_6
   *
   * Purpose      Tests compound conversions when the destination has the same
   *              fields as the source but one or more of the fields are
   *              larger.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_6()
  {
      typedef struct {
          short b;
          short d;
      } src_typ_t;
  
      typedef struct {
          long b;
          long d;
      } dst_typ_t;
  
      src_typ_t *    s_ptr;
      dst_typ_t *    d_ptr;
      int            i;
      const int      nelmts = NTESTELEM;
      unsigned char *buf = NULL, *orig = NULL, *bkg = NULL;
  
      // Output message about test being performed
      SUBTEST("Compound Element Growing");
      try {
          /* Sizes should be the same, but be careful just in case */
          buf  = (unsigned char *)HDmalloc(nelmts * MAX(sizeof(src_typ_t), sizeof(dst_typ_t)));
          bkg  = (unsigned char *)HDmalloc(nelmts * sizeof(dst_typ_t));
          orig = (unsigned char *)HDmalloc(nelmts * sizeof(src_typ_t));
          for (i = 0; i < nelmts; i++) {
              s_ptr    = ((src_typ_t *)orig) + i;
              s_ptr->b = (i * 8 + 1) & 0x7fff;
              s_ptr->d = (i * 8 + 6) & 0x7fff;
          }
          memcpy(buf, orig, nelmts * sizeof(src_typ_t));
  
          /* Build hdf5 datatypes */
          CompType st(sizeof(src_typ_t));
          st.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_SHORT);
          st.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_SHORT);
  
          CompType dt(sizeof(dst_typ_t));
          dt.insertMember("b", HOFFSET(dst_typ_t, b), PredType::NATIVE_LONG);
          dt.insertMember("d", HOFFSET(dst_typ_t, d), PredType::NATIVE_LONG);
  
          /* Perform the conversion */
          st.convert(dt, (size_t)nelmts, buf, bkg);
  
          /* Compare results */
          for (i = 0; i < nelmts; i++) {
              s_ptr = ((src_typ_t *)orig) + i;
              d_ptr = ((dst_typ_t *)buf) + i;
              if (s_ptr->b != d_ptr->b || s_ptr->d != d_ptr->d) {
                  H5_FAILED();
                  cerr << "    i=" << i << endl;
                  cerr << "    src={b=" << s_ptr->b << ", d=" << s_ptr->d << "}" << endl;
                  cerr << "    dst={b=" << d_ptr->b << ", d=" << d_ptr->d << "}" << endl;
              } // if
          }     // for
  
          /* Release resources */
          HDfree(buf);
          HDfree(bkg);
          HDfree(orig);
          s_ptr = NULL;
          d_ptr = NULL;
          st.close();
          dt.close();
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  } // test_compound_6()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_7
   *
   * Purpose      Tests inserting fields into compound datatypes when the field
   *              overlaps the end of the compound datatype.
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use C version)
   *              January, 2007
   *-------------------------------------------------------------------------
   */
  static void
  test_compound_7()
  {
      typedef struct {
          int   a;
          float b;
          long  c;
      } s1_typ_t;
  
      typedef struct {
          int    a;
          float  b;
          long   c;
          double d;
      } s2_typ_t;
  
      // Output message about test being performed
      SUBTEST("Compound Element Insertion");
      try {
          CompType tid1(sizeof(s1_typ_t));
  
          tid1.insertMember("a", HOFFSET(s1_typ_t, a), PredType::NATIVE_INT);
          tid1.insertMember("b", HOFFSET(s1_typ_t, b), PredType::NATIVE_FLOAT);
          tid1.insertMember("c", HOFFSET(s1_typ_t, c), PredType::NATIVE_LONG);
  
          size_t type_size = tid1.getSize();
          verify_val(type_size, sizeof(s1_typ_t), "DataType::getSize", __LINE__, __FILE__);
  
          CompType tid2;
          tid2.copy(tid1);
  
          type_size = tid2.getSize();
          verify_val_noteq(type_size, sizeof(s2_typ_t), "DataType::getSize", __LINE__, __FILE__);
  
          /* Should not be able to insert field past end of compound datatype */
          try {
              tid2.insertMember("d", HOFFSET(s2_typ_t, d), PredType::NATIVE_DOUBLE);
              // Should FAIL but didn't, so throw an invalid action exception
              throw InvalidActionException("CompType::insertMember",
                                           "Attempted to insert field past end of compound data type.");
          }
          catch (DataTypeIException &err) {
          }
  
          /* Release resources */
          tid1.close();
          tid2.close();
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  } // test_compound_7()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound_set_size
   *
   * Purpose      Tests member function setSize() on compound datatype
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler (use partial C version test_ooo_order)
   *              March, 2014
   *-------------------------------------------------------------------------
   */
  const H5std_string COMPFILE("tcompound_types.h5");
  
  static void
  test_compound_set_size()
  {
      typedef struct {
          int a, b, c[4], d, e;
      } src_typ_t;
  
      // Output message about test being performed
      SUBTEST("Setting Size on Compound Datatype");
      try {
          // Create File
          H5File file(COMPFILE, H5F_ACC_TRUNC);
  
          // Create a compound datatype
          CompType dtype(sizeof(src_typ_t));
  
          dtype.insertMember("a", HOFFSET(src_typ_t, a), PredType::NATIVE_INT);
          dtype.insertMember("b", HOFFSET(src_typ_t, b), PredType::NATIVE_FLOAT);
          dtype.insertMember("c", HOFFSET(src_typ_t, c), PredType::NATIVE_LONG);
          dtype.insertMember("d", HOFFSET(src_typ_t, d), PredType::NATIVE_DOUBLE);
  
          // Verify that the compound is not packed
          // bool packed = dtype.packed(); // not until C library provides API
          // verify_val(packed, FALSE, "DataType::packed", __LINE__, __FILE__);
  
          dtype.commit(file, "dtype");
  
          // Close the type and file
          dtype.close();
          file.close();
  
          // Open the file for read/write
          file.openFile(COMPFILE, H5F_ACC_RDWR);
  
          // Open the data type "dtype"
          CompType dtype_tmp = file.openCompType("dtype");
  
          // Make a copy of the data type
          dtype.copy(dtype_tmp);
  
          // Verify that the compound is not packed
          // packed = dtype_tmp.packed(); // not until C library provides API
          // verify_val(packed, FALSE, "DataType::packed", __LINE__, __FILE__);
  
          // Expand the type, and verify that it became unpacked
          dtype.setSize((size_t)33);
          // packed = dtype.packed(); // not until C library provides API
          // verify_val(packed, FALSE, "DataType::packed", __LINE__, __FILE__);
  
          // Verify setSize() actually set size
          size_t new_size = dtype.getSize();
          verify_val(new_size, (size_t)33, "DataType::getSize", __LINE__, __FILE__);
  
          // Shrink the type, and verify that it became packed
          dtype.setSize((size_t)32);
          // packed = dtype.packed(); // not until C library provides API
          // verify_val(packed, TRUE, "DataType::packed", __LINE__, __FILE__);
  
          // Verify setSize() actually set size again
          new_size = dtype.getSize();
          verify_val(new_size, (size_t)32, "DataType::getSize", __LINE__, __FILE__);
  
          /* Close types and file */
          dtype_tmp.close();
          dtype.close();
          file.close();
  
          PASSED();
      } // end of try block
  
      catch (Exception &E) {
          issue_fail_msg(E.getCFuncName(), __LINE__, __FILE__, E.getCDetailMsg());
      }
  } // test_compound_set_size()
  
  /*-------------------------------------------------------------------------
   * Function:    test_compound
   *
   * Purpose      Main compound datatype testing routine
   *
   * Return       None
   *
   * Programmer   Binh-Minh Ribler
   *              January 2007
   *-------------------------------------------------------------------------
   */
  extern "C" void
  test_compound()
  {
      // Output message about test being performed
      MESSAGE(5, ("Testing Compound Data Type operations\n"));
  
      test_compound_1();        // various things about compound data types
      test_compound_2();        // compound element reordering
      test_compound_3();        // compound datatype subset conversions
      test_compound_4();        // compound element shrinking & reordering
      test_compound_5();        // optimized struct converter
      test_compound_6();        // compound element growing
      test_compound_7();        // compound element insertion
      test_compound_set_size(); // set size on compound data types
  } // test_compound()
  
  /*-------------------------------------------------------------------------
   * Function:    cleanup_compound
   *
   * Purpose      Cleanup temporary test files - nothing at this time.
   *
   * Return       None
   *-------------------------------------------------------------------------
   */
  extern "C" void
  cleanup_compound()
  {
      HDremove(COMPFILE.c_str());
  } // cleanup_file
  