/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#ifndef GEODE_INTEGRATION_TEST_BUILTINCACHEABLEWRAPPERS_H_
#define GEODE_INTEGRATION_TEST_BUILTINCACHEABLEWRAPPERS_H_

#include <limits.h>
#include <cstdlib>
#include <wchar.h>
#include <random>

#include <ace/Date_Time.h>

#include "CacheHelper.hpp"
#include "CacheRegionHelper.hpp"
#include "CacheableWrapper.hpp"
#include "CacheImpl.hpp"
#include "testUtils.hpp"

#include <geode/CacheableFileName.hpp>
#include <geode/CacheableUndefined.hpp>
#include <geode/CacheableObjectArray.hpp>

namespace CacheableHelper {

using apache::geode::client::Cacheable;
using apache::geode::client::CacheableArrayList;
using apache::geode::client::CacheableBoolean;
using apache::geode::client::CacheableByte;
using apache::geode::client::CacheableBytes;
using apache::geode::client::CacheableCharacter;
using apache::geode::client::CacheableDate;
using apache::geode::client::CacheableDouble;
using apache::geode::client::CacheableDoubleArray;
using apache::geode::client::CacheableFileName;
using apache::geode::client::CacheableFloat;
using apache::geode::client::CacheableFloatArray;
using apache::geode::client::CacheableHashMap;
using apache::geode::client::CacheableHashSet;
using apache::geode::client::CacheableHashTable;
using apache::geode::client::CacheableIdentityHashMap;
using apache::geode::client::CacheableInt16;
using apache::geode::client::CacheableInt16Array;
using apache::geode::client::CacheableInt32;
using apache::geode::client::CacheableInt32Array;
using apache::geode::client::CacheableInt64;
using apache::geode::client::CacheableInt64Array;
using apache::geode::client::CacheableKey;
using apache::geode::client::CacheableLinkedHashSet;
using apache::geode::client::CacheableLinkedList;
using apache::geode::client::CacheableObjectArray;
using apache::geode::client::CacheableStack;
using apache::geode::client::CacheableString;
using apache::geode::client::CacheableStringArray;
using apache::geode::client::CacheableUndefined;
using apache::geode::client::CacheableVector;
using apache::geode::client::CacheHelper;
using apache::geode::client::Serializable;
using apache::geode::client::internal::DataSerializablePrimitive;
using apache::geode::client::internal::DSCode;

using apache::geode::client::testing::CacheableWrapper;
using apache::geode::client::testing::CacheableWrapperFactory;

using unitTests::TestUtils;

const uint32_t m_crc32Table[] = {
    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
    0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};

inline double random(double maxValue) {
  static thread_local std::default_random_engine generator(
      std::random_device{}());
  return std::uniform_real_distribution<double>{0.0, maxValue}(generator);
}

template <typename TPRIM>
inline TPRIM random(TPRIM maxValue) {
  return static_cast<TPRIM>(random(static_cast<double>(maxValue)));
}

// This returns an array allocated on heap
// which should be freed by the user.
template <typename TPRIM>
inline std::vector<TPRIM> randomArray(int32_t size, TPRIM maxValue) {
  ASSERT(size > 0, "The size of the array should be greater than zero.");
  std::vector<TPRIM> array;
  array.reserve(size);

  for (int32_t index = 0; index < size; index++) {
    array.push_back(random(maxValue));
  }
  return array;
}

// Taken from GsRandom::getAlphanumericString
inline void randomString(int32_t size, std::string& randStr) {
  ASSERT(size > 0, "The size of the string should be greater than zero.");

  static const char chooseFrom[] =
      "0123456789 abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  static const int32_t chooseSize = sizeof(chooseFrom) - 1;

  randStr.resize(size);
  for (int32_t index = 0; index < size; index++) {
    randStr[index] = chooseFrom[random(chooseSize)];
  }
}

inline void randomString(int32_t size, std::wstring& randStr,
                         bool useASCII = false) {
  ASSERT(size > 0, "The size of the string should be greater than zero.");

  static const char chooseFrom[] =
      "0123456789 abcdefghijklmnopqrstuvwxyz_ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  static const int32_t chooseSize = sizeof(chooseFrom) - 1;

  randStr.resize(size);
  for (int32_t index = 0; index < size; index++) {
    if (useASCII) {
      randStr[index] = static_cast<wchar_t>(chooseFrom[random(chooseSize)]);
    } else {
      randStr[index] = static_cast<wchar_t>(
          static_cast<uint16_t>(random(UCHAR_MAX)) + 0x0901);
    }
  }
}

inline uint32_t crc32(const uint8_t* buffer, size_t bufLen) {
  if (buffer == nullptr || bufLen == 0) {
    return 0;
  }

  uint32_t crc = 0xffffffff;

  for (size_t index = 0; index < bufLen; index++) {
    crc =
        ((crc >> 8) & 0x00ffffff) ^ m_crc32Table[(crc ^ buffer[index]) & 0xff];
  }
  return ~crc;
}

inline uint32_t crc32(const int8_t* buffer, size_t bufLen) {
  return crc32(reinterpret_cast<const uint8_t*>(buffer), bufLen);
}

template <typename TPRIM>
inline uint32_t crc32(TPRIM value) {
  auto output = CacheHelper::getHelper().getCache()->createDataOutput();
  apache::geode::client::serializer::writeObject(output, value);
  return crc32(output.getBuffer(), output.getBufferLength());
}

template <typename TPRIM>
inline uint32_t crc32Array(const std::vector<TPRIM> arr) {
  auto output = CacheHelper::getHelper().getCache()->createDataOutput();
  for (auto obj : arr) {
    apache::geode::client::serializer::writeObject(output, obj);
  }
  return crc32(output.getBuffer(), output.getBufferLength());
}

inline bool isContainerTypeId(DSCode typeId) {
  return (typeId == DSCode::CacheableObjectArray) ||
         (typeId == DSCode::CacheableVector) ||
         (typeId == DSCode::CacheableHashMap) ||
         (typeId == DSCode::CacheableHashSet) ||
         (typeId == DSCode::CacheableStack) ||
         (typeId == DSCode::CacheableArrayList) ||
         (typeId == DSCode::CacheableHashTable) ||
         (typeId == DSCode::CacheableIdentityHashMap) ||
         (typeId == DSCode::CacheableLinkedHashSet) ||
         (typeId == DSCode::CacheableLinkedList);
}

// Cacheable types that can be used as keys

class CacheableBooleanWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  inline CacheableBooleanWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableBooleanWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return 2; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableBoolean::create(keyIndex % 2);
  }

  void initRandomValue(int32_t) override {
    m_cacheableObject = CacheableBoolean::create(
        CacheableHelper::random<uint8_t>(UCHAR_MAX) % 2);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableBoolean* obj =
        dynamic_cast<const CacheableBoolean*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<uint8_t>(obj->value() ? 1 : 0);
  }
};

class CacheableByteWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  inline CacheableByteWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableByteWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return UCHAR_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableByte::create(static_cast<uint8_t>(keyIndex));
  }

  void initRandomValue(int32_t) override {
    m_cacheableObject =
        CacheableByte::create(CacheableHelper::random<uint8_t>(UCHAR_MAX));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableByte* obj = dynamic_cast<const CacheableByte*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<uint8_t>(obj->value());
  }
};

class CacheableDoubleWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableDoubleWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableDoubleWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableDouble::create(static_cast<double>(keyIndex));
  }

  void initRandomValue(int32_t maxSize) override {
    m_cacheableObject = CacheableDouble::create(
        CacheableHelper::random(static_cast<double>(maxSize)));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableDouble* obj =
        dynamic_cast<const CacheableDouble*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<double>(obj->value());
  }
};

class CacheableDateWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableDateWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableDateWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    // Seconds since epoch for June 26, 16:44
    time_t offset = 1182901465;
    m_cacheableObject = CacheableDate::create(offset + keyIndex);
  }

  void initRandomValue(int32_t) override {
    auto rnd = CacheableHelper::random<int32_t>(INT_MAX);

    auto timeofday = std::chrono::time_point_cast<std::chrono::seconds>(
                         std::chrono::system_clock::now())
                         .time_since_epoch()
                         .count();
    time_t epoctime =
        static_cast<time_t>(timeofday + (rnd * (rnd & 1 ? -1 : 1)));

    m_cacheableObject = CacheableDate::create(epoctime);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableDate* obj = dynamic_cast<const CacheableDate*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<int64_t>(obj->milliseconds());
  }
};

class CacheableFileNameWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableFileNameWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableFileNameWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t maxSize) override {
    maxSize %= (0xFFFF + 1);
    if (maxSize < 11) {
      maxSize = 11;
    }
    std::string baseStr(maxSize - 10, 'A');
    baseStr.append(TestUtils::zeroPaddedStringFromInt(keyIndex, 10));

// make first caharacter as a '/' so java does not change the path
// taking it to be a relative path
#ifdef WIN32
    baseStr[0] = L'C';
    baseStr[1] = L':';
    baseStr[2] = L'\\';
#else
    baseStr[0] = L'/';
#endif
    m_cacheableObject = CacheableFileName::create(baseStr);
  }

  void initRandomValue(int32_t maxSize) override {
    maxSize %= (0xFFFF + 1);
    std::string randStr;
    CacheableHelper::randomString(maxSize, randStr);
    // make first caharacter as a '/' so java does not change the path
    // taking it to be a relative path
    randStr[0] = '/';
    m_cacheableObject = CacheableFileName::create(randStr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto&& obj = std::dynamic_pointer_cast<CacheableFileName>(object);
    return (obj ? CacheableHelper::crc32(
                      reinterpret_cast<const uint8_t*>(obj->value().c_str()),
                      obj->length())
                : 0);
  }
};

class CacheableFloatWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableFloatWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableFloatWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableFloat::create(static_cast<float>(keyIndex));
  }

  void initRandomValue(int32_t maxSize) override {
    m_cacheableObject = CacheableFloat::create(
        CacheableHelper::random(static_cast<float>(maxSize)));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableFloat* obj =
        dynamic_cast<const CacheableFloat*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<float>(obj->value());
  }
};

class CacheableInt16Wrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableInt16Wrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableInt16Wrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return SHRT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableInt16::create(static_cast<int16_t>(keyIndex));
  }

  void initRandomValue(int32_t) override {
    m_cacheableObject =
        CacheableInt16::create(CacheableHelper::random<int16_t>(SHRT_MAX));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableInt16* obj =
        dynamic_cast<const CacheableInt16*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<int16_t>(obj->value());
  }
};

class CacheableInt32Wrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableInt32Wrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableInt32Wrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableInt32::create(keyIndex);
  }

  void initRandomValue(int32_t) override {
    m_cacheableObject =
        CacheableInt32::create(CacheableHelper::random<int32_t>(INT_MAX));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableInt32* obj =
        dynamic_cast<const CacheableInt32*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<int32_t>(obj->value());
  }
};

class CacheableInt64Wrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableInt64Wrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableInt64Wrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableInt64::create(static_cast<int64_t>(keyIndex));
  }

  void initRandomValue(int32_t) override {
    int64_t rnd = CacheableHelper::random<int64_t>(INT_MAX);
    rnd = (rnd << 32) + CacheableHelper::random<int64_t>(INT_MAX);
    m_cacheableObject = CacheableInt64::create(rnd);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableInt64* obj =
        dynamic_cast<const CacheableInt64*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<int64_t>(obj->value());
  }
};

class CacheableStringWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableStringWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableStringWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t maxSize) override {
    maxSize %= (0xFFFF + 1);
    if (maxSize < 11) {
      maxSize = 11;
    }
    std::string baseStr(maxSize - 10, 'A');
    baseStr.append(TestUtils::zeroPaddedStringFromInt(keyIndex, 10));
    m_cacheableObject = CacheableString::create(baseStr);
  }

  void initRandomValue(int32_t maxSize) override {
    maxSize %= (0xFFFF + 1);
    std::string randStr;
    CacheableHelper::randomString(maxSize, randStr);
    m_cacheableObject = CacheableString::create(randStr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableString* obj =
        dynamic_cast<const CacheableString*>(object.get());
    return (obj != nullptr
                ? CacheableHelper::crc32(
                      reinterpret_cast<const uint8_t*>(obj->value().c_str()),
                      obj->length())
                : 0);
  }
};

class CacheableHugeStringWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableHugeStringWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableHugeStringWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t maxSize) override {
    if (maxSize <= 0xFFFF)  // ensure its larger than 64k
    {
      maxSize += (0xFFFF + 1);
    }
    std::string baseStr(maxSize - 10, 'A');
    baseStr.append(TestUtils::zeroPaddedStringFromInt(keyIndex, 10));
    m_cacheableObject = CacheableString::create(baseStr);
  }

  void initRandomValue(int32_t maxSize) override {
    if (maxSize <= 0xFFFF)  // ensure its larger than 64k
    {
      maxSize += (0xFFFF + 1);
    }
    std::string randStr;
    CacheableHelper::randomString(maxSize, randStr);
    m_cacheableObject = CacheableString::create(randStr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableString* obj =
        dynamic_cast<const CacheableString*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32(
        reinterpret_cast<const uint8_t*>(obj->value().c_str()), obj->length());
  }
};

class CacheableHugeUnicodeStringWrapper : public CacheableWrapper {
 public:
  CacheableHugeUnicodeStringWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableHugeUnicodeStringWrapper();
  }

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t maxSize) override {
    if (maxSize <= 0xFFFF)  // ensure its larger than 64k
    {
      maxSize += (0xFFFF + 1);
    }
    std::wstring baseStr(maxSize - 10, L'\x0905');
    wchar_t indexStr[15];
    swprintf(indexStr, 14, L"%10d", keyIndex);
    baseStr.append(indexStr);
    m_cacheableObject = CacheableString::create(baseStr);
  }

  void initRandomValue(int32_t maxSize) override {
    if (maxSize <= 0xFFFF)  // ensure its larger than 64k
    {
      maxSize += (0xFFFF + 1);
    }
    std::wstring randStr;
    CacheableHelper::randomString(maxSize, randStr);
    m_cacheableObject = CacheableString::create(randStr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto&& obj = std::dynamic_pointer_cast<CacheableString>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32(
        reinterpret_cast<const uint8_t*>(obj->value().c_str()),
        obj->length() * sizeof(std::string::value_type));
  }
};

class CacheableUnicodeStringWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableUnicodeStringWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableUnicodeStringWrapper();
  }

  // CacheableWrapper members

  int32_t maxKeys() const override { return INT_MAX; }

  void initKey(int32_t keyIndex, int32_t maxSize) override {
    maxSize %= 21800;  // so that encoded length is within 64k
    if (maxSize < 11) {
      maxSize = 11;
    }
    std::wstring baseStr(maxSize - 10, L'\x0905');
    wchar_t indexStr[15];
    swprintf(indexStr, 14, L"%10d", keyIndex);
    baseStr.append(indexStr);
    m_cacheableObject = CacheableString::create(baseStr);
  }

  void initRandomValue(int32_t maxSize) override {
    maxSize %= 21800;  // so that encoded length is within 64k
    std::wstring randStr;
    CacheableHelper::randomString(maxSize, randStr);
    m_cacheableObject = CacheableString::create(randStr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto&& obj = std::dynamic_pointer_cast<CacheableString>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32(
        reinterpret_cast<const uint8_t*>(obj->value().c_str()),
        obj->length() * sizeof(std::string::value_type));
  }
};

class CacheableWideCharWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableWideCharWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableWideCharWrapper(); }

  // CacheableWrapper members

  int32_t maxKeys() const override { return SHRT_MAX; }

  void initKey(int32_t keyIndex, int32_t) override {
    m_cacheableObject = CacheableCharacter::create(keyIndex);
  }

  void initRandomValue(int32_t) override {
    m_cacheableObject =
        CacheableCharacter::create(CacheableHelper::random<char16_t>(SHRT_MAX));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto obj = std::dynamic_pointer_cast<const CacheableCharacter>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32<char16_t>(obj->value());
  }
};

// Other cacheable types that cannot be used as keys

template <typename HMAPTYPE>
class CacheableHashMapTypeWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableHashMapTypeWrapper<HMAPTYPE>() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableHashMapTypeWrapper<HMAPTYPE>();
  }

  // CacheableWrapper members

  void initRandomValue(int32_t maxSize) override {
    m_cacheableObject = HMAPTYPE::create(maxSize);
    HMAPTYPE* chmp = dynamic_cast<HMAPTYPE*>(m_cacheableObject.get());
    ASSERT(chmp != nullptr, "initRandomValue: null object.");
    auto keyTypeIds = CacheableWrapperFactory::getRegisteredKeyTypes();
    auto valTypeIds = CacheableWrapperFactory::getRegisteredValueTypes();

    for (std::vector<DSCode>::iterator keyIter = keyTypeIds.begin();
         keyIter != keyTypeIds.end(); keyIter++) {
      int item = 0;

      for (std::vector<DSCode>::iterator valIter = valTypeIds.begin();
           valIter != valTypeIds.end(); valIter++) {
        if (CacheableHelper::isContainerTypeId(static_cast<DSCode>(*valIter))) {
          continue;
        }
        if ((*valIter == DSCode::CacheableASCIIStringHuge ||
             *valIter == DSCode::CacheableStringHuge) &&
            !(*keyIter == DSCode::CacheableBoolean)) {
          continue;
        }
        if ((*keyIter == DSCode::CacheableASCIIStringHuge ||
             *keyIter == DSCode::CacheableStringHuge) &&
            !(*valIter == DSCode::CacheableBoolean)) {
          continue;
        }
        // null object does not work on server side during deserialization
        if (*valIter == DSCode::CacheableNullString) {
          continue;
        }

        const auto keyWrapper = std::unique_ptr<CacheableWrapper>(
            CacheableWrapperFactory::createInstance(*keyIter));
        ASSERT(keyWrapper != nullptr,
               "initRandomValue: keyWrapper null object.");
        if (item > keyWrapper->maxKeys()) {
        }
        const auto valWrapper = std::unique_ptr<CacheableWrapper>(
            CacheableWrapperFactory::createInstance(*valIter));
        ASSERT(valWrapper != nullptr,
               "initRandomValue: valWrapper null object.");
        keyWrapper->initKey(((static_cast<int8_t>(*keyIter)) << 8) + item,
                            maxSize);
        valWrapper->initRandomValue(maxSize);
        chmp->emplace(
            std::dynamic_pointer_cast<CacheableKey>(keyWrapper->getCacheable()),
            valWrapper->getCacheable());
        item++;
      }
    }
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto map = std::dynamic_pointer_cast<const HMAPTYPE>(object);
    ASSERT(map != nullptr, "getCheckSum: null object.");
    uint32_t chksum = 0;

    for (const auto& obj : *map) {
      if (const auto key =
              std::dynamic_pointer_cast<DataSerializablePrimitive>(obj.first)) {
        const auto cwpKey = std::unique_ptr<CacheableWrapper>(
            CacheableWrapperFactory::createInstance(key->getDsCode()));

        uint32_t cwpObjCkSum = 0;
        if (const auto value =
                std::dynamic_pointer_cast<DataSerializablePrimitive>(
                    obj.second)) {
          const auto cwpVal = std::unique_ptr<CacheableWrapper>(
              CacheableWrapperFactory::createInstance(value->getDsCode()));
          cwpObjCkSum = cwpVal->getCheckSum(value);
        }

        chksum ^= (cwpKey->getCheckSum(key) ^ cwpObjCkSum);
      }
    }

    return chksum;
  }
};

typedef CacheableHashMapTypeWrapper<CacheableHashMap> CacheableHashMapWrapper;

typedef CacheableHashMapTypeWrapper<CacheableHashTable>
    CacheableHashTableWrapper;

typedef CacheableHashMapTypeWrapper<CacheableIdentityHashMap>
    CacheableIdentityHashMapWrapper;

template <typename HSETTYPE>
class CacheableHashSetTypeWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableHashSetTypeWrapper<HSETTYPE>() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableHashSetTypeWrapper<HSETTYPE>();
  }

  // CacheableWrapper members

  void initRandomValue(int32_t maxSize) override {
    auto set =
        std::dynamic_pointer_cast<HSETTYPE>(HSETTYPE::createDeserializable());
    auto keyTypeIds = CacheableWrapperFactory::getRegisteredKeyTypes();
    size_t sizeOfTheVector = keyTypeIds.size();
    maxSize = maxSize / static_cast<int32_t>(sizeOfTheVector) + 1;
    for (size_t i = 0; i < sizeOfTheVector; i++) {
      DSCode keyTypeId = keyTypeIds[i];
      auto wrapper = CacheableWrapperFactory::createInstance(keyTypeId);
      wrapper->initRandomValue(maxSize);
      auto cptr = wrapper->getCacheable();
      set->insert(
          std::dynamic_pointer_cast<CacheableKey>(wrapper->getCacheable()));
      delete wrapper;
    }
    m_cacheableObject = set;
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto set = std::dynamic_pointer_cast<HSETTYPE>(object);
    ASSERT(set != nullptr, "getCheckSum: null object.");
    uint32_t checkSum = 0;

    for (const auto& obj : *set) {
      if (auto primitive =
              std::dynamic_pointer_cast<DataSerializablePrimitive>(obj)) {
        const auto typeId = primitive->getDsCode();
        const auto wrapper = std::unique_ptr<CacheableWrapper>(
            CacheableWrapperFactory::createInstance(typeId));
        checkSum ^= wrapper->getCheckSum(primitive);
      }
    }
    return checkSum;
  }
};

typedef CacheableHashSetTypeWrapper<CacheableHashSet> CacheableHashSetWrapper;

typedef CacheableHashSetTypeWrapper<CacheableLinkedHashSet>
    CacheableLinkedHashSetWrapper;

class CacheableBytesWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableBytesWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableBytesWrapper(); }

  void initRandomValue(int32_t maxSize) override {
    auto randArr = CacheableHelper::randomArray<uint8_t>(maxSize, UCHAR_MAX);
    m_cacheableObject = CacheableBytes::create(
        std::vector<int8_t>(std::begin(randArr), std::end(randArr)));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const CacheableBytes* obj =
        dynamic_cast<const CacheableBytes*>(object.get());
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32(obj->value().data(), obj->length());
  }
};

class CacheableDoubleArrayWrapper : public CacheableWrapper {
 public:
  CacheableDoubleArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableDoubleArrayWrapper();
  }

  void initRandomValue(int32_t maxSize) override {
    maxSize = maxSize / sizeof(double) + 1;
    auto randArr =
        CacheableHelper::randomArray(maxSize, static_cast<double>(INT_MAX));
    m_cacheableObject = CacheableDoubleArray::create(randArr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const auto obj =
        std::dynamic_pointer_cast<const CacheableDoubleArray>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32Array(obj->value());
  }
};

class CacheableFloatArrayWrapper : public CacheableWrapper {
 public:
  CacheableFloatArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableFloatArrayWrapper(); }

  void initRandomValue(int32_t maxSize) override {
    maxSize = maxSize / sizeof(float) + 1;
    auto randArr =
        CacheableHelper::randomArray(maxSize, static_cast<float>(INT_MAX));
    m_cacheableObject = CacheableFloatArray::create(randArr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const auto obj =
        std::dynamic_pointer_cast<const CacheableFloatArray>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32Array(obj->value());
  }
};

class CacheableInt16ArrayWrapper : public CacheableWrapper {
 public:
  CacheableInt16ArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableInt16ArrayWrapper(); }

  void initRandomValue(int32_t maxSize) override {
    maxSize = maxSize / sizeof(int16_t) + 1;
    auto randArr = CacheableHelper::randomArray<int16_t>(maxSize, SHRT_MAX);
    m_cacheableObject = CacheableInt16Array::create(randArr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const auto obj =
        std::dynamic_pointer_cast<const CacheableInt16Array>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32Array(obj->value());
  }
};

class CacheableInt32ArrayWrapper : public CacheableWrapper {
 public:
  CacheableInt32ArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableInt32ArrayWrapper(); }

  void initRandomValue(int32_t maxSize) override {
    maxSize = maxSize / sizeof(int32_t) + 1;
    auto randArr = CacheableHelper::randomArray<int32_t>(maxSize, INT_MAX);
    m_cacheableObject = CacheableInt32Array::create(randArr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const auto obj =
        std::dynamic_pointer_cast<const CacheableInt32Array>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32Array(obj->value());
  }
};

class CacheableInt64ArrayWrapper : public CacheableWrapper {
 public:
  CacheableInt64ArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableInt64ArrayWrapper(); }

  void initRandomValue(int32_t maxSize) override {
    maxSize = maxSize / sizeof(int64_t) + 1;
    auto randArr = CacheableHelper::randomArray<int64_t>(maxSize, INT_MAX);
    m_cacheableObject = CacheableInt64Array::create(randArr);
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    const auto obj =
        std::dynamic_pointer_cast<const CacheableInt64Array>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    return CacheableHelper::crc32Array(obj->value());
  }
};

class CacheableNullStringWrapper : public CacheableWrapper {
 public:
  CacheableNullStringWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() { return new CacheableNullStringWrapper(); }

  void initRandomValue(int32_t) override {
    m_cacheableObject = CacheableString::create(static_cast<char*>(nullptr));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    ASSERT(object == nullptr, "getCheckSum: expected null object");
    return 0;
  }
};

class CacheableStringArrayWrapper : public CacheableWrapper {
 public:
  CacheableStringArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableStringArrayWrapper();
  }

  void initRandomValue(int32_t maxSize) override {
    int32_t arraySize = 16;
    maxSize = maxSize / arraySize;
    if (maxSize < 2) {
      maxSize = 2;
    }

    std::shared_ptr<CacheableString>* randArr =
        new std::shared_ptr<CacheableString>[arraySize];
    for (int32_t arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) {
      if (arrayIndex % 2 == 0) {
        std::string randStr;
        CacheableHelper::randomString(maxSize, randStr);
        randArr[arrayIndex] = CacheableString::create(randStr);
      } else {
        std::wstring randStr;
        CacheableHelper::randomString(maxSize, randStr);
        randArr[arrayIndex] = CacheableString::create(randStr);
      }
    }
    m_cacheableObject = CacheableStringArray::create(
        std::vector<std::shared_ptr<CacheableString>>(randArr,
                                                      randArr + arraySize));
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto&& obj = std::dynamic_pointer_cast<CacheableStringArray>(object);
    ASSERT(obj != nullptr, "getCheckSum: null object.");
    uint32_t checkSum = 0;
    std::shared_ptr<CacheableString> str;
    for (int32_t index = 0; index < obj->length(); index++) {
      str = obj->operator[](index);
      checkSum ^= CacheableHelper::crc32(
          reinterpret_cast<const uint8_t*>(str->value().c_str()),
          str->length() * sizeof(std::string::value_type));
    }
    return checkSum;
  }
};

template <typename VECTTYPE>
class CacheableVectorTypeWrapper : public CacheableWrapper {
 public:
  CacheableVectorTypeWrapper<VECTTYPE>() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableVectorTypeWrapper<VECTTYPE>();
  }

  void initRandomValue(int32_t maxSize) override {
    auto vec =
        std::dynamic_pointer_cast<VECTTYPE>(VECTTYPE::createDeserializable());
    auto valueTypeIds = CacheableWrapperFactory::getRegisteredValueTypes();
    size_t sizeOfTheVector = valueTypeIds.size();
    maxSize = maxSize / static_cast<int32_t>(sizeOfTheVector) + 1;
    for (size_t i = 0; i < sizeOfTheVector; i++) {
      DSCode valueTypeId = valueTypeIds[i];
      if (!CacheableHelper::isContainerTypeId(
              static_cast<DSCode>(valueTypeId))) {
        auto wrapper = CacheableWrapperFactory::createInstance(valueTypeId);
        wrapper->initRandomValue(maxSize);
        vec->push_back(wrapper->getCacheable());
        delete wrapper;
      }
    }
    m_cacheableObject = vec;
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto vec = std::dynamic_pointer_cast<VECTTYPE>(object);
    ASSERT(vec != nullptr, "getCheckSum: null object.");
    uint32_t checkSum = 0;
    for (const auto& obj : *vec) {
      if (auto primitive =
              std::dynamic_pointer_cast<DataSerializablePrimitive>(obj)) {
        auto typeId = primitive->getDsCode();
        auto wrapper = std::unique_ptr<CacheableWrapper>(
            CacheableWrapperFactory::createInstance(typeId));
        checkSum ^= wrapper->getCheckSum(primitive);
      }
    }
    return checkSum;
  }
};

typedef CacheableVectorTypeWrapper<CacheableVector> CacheableVectorWrapper;

typedef CacheableVectorTypeWrapper<CacheableArrayList>
    CacheableArrayListWrapper;

typedef CacheableVectorTypeWrapper<CacheableLinkedList>
    CacheableLinkedListWrapper;

typedef CacheableVectorTypeWrapper<CacheableStack> CacheableStackWrapper;

class CacheableObjectArrayWrapper : public CacheableWrapper {
 public:
  // Constructor and factory function

  CacheableObjectArrayWrapper() : CacheableWrapper(nullptr) {}

  static CacheableWrapper* create() {
    return new CacheableObjectArrayWrapper();
  }

  // CacheableWrapper members

  void initRandomValue(int32_t maxSize) override {
    auto arr = std::dynamic_pointer_cast<CacheableObjectArray>(
        CacheableObjectArray::createDeserializable());
    auto valueTypeIds = CacheableWrapperFactory::getRegisteredValueTypes();
    size_t sizeOfTheVector = valueTypeIds.size();
    maxSize = maxSize / static_cast<int32_t>(sizeOfTheVector) + 1;
    for (size_t i = 0; i < sizeOfTheVector; i++) {
      DSCode valueTypeId = valueTypeIds[i];
      if (!CacheableHelper::isContainerTypeId(
              static_cast<DSCode>(valueTypeId))) {
        auto wrapper = CacheableWrapperFactory::createInstance(valueTypeId);
        wrapper->initRandomValue(maxSize);
        arr->push_back(wrapper->getCacheable());
        delete wrapper;
      }
    }
    m_cacheableObject = arr;
  }

  uint32_t getCheckSum(const std::shared_ptr<Cacheable> object) const override {
    auto&& arr = std::dynamic_pointer_cast<CacheableObjectArray>(object);
    ASSERT(arr != nullptr, "getCheckSum: null object.");
    uint32_t checkSum = 0;
    for (const auto& obj : *arr) {
      if (auto primitive =
              std::dynamic_pointer_cast<DataSerializablePrimitive>(obj)) {
        auto wrapper =
            CacheableWrapperFactory::createInstance(primitive->getDsCode());
        checkSum ^= wrapper->getCheckSum(obj);
        delete wrapper;
      }
    }
    return checkSum;
  }
};

void registerBuiltins(bool isRegisterFileName = false) {
  // Initialize the random number generator.
  srand(getpid() + static_cast<int>(time(nullptr)));

  // Register the builtin cacheable keys
  CacheableWrapperFactory::registerType(DSCode::CacheableBoolean,
                                        "CacheableBoolean",
                                        CacheableBooleanWrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableByte, "CacheableByte",
                                        CacheableByteWrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableDouble,
                                        "CacheableDouble",
                                        CacheableDoubleWrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableDate, "CacheableDate",
                                        CacheableDateWrapper::create, true);
  if (isRegisterFileName) {
#ifdef _WIN32
    // TODO: windows requires some serious tweaking to get this to work
    CacheableWrapperFactory::registerType(
        DSCode::CacheableFileName, "CacheableFileName",
        CacheableFileNameWrapper::create, true);
#endif
  }
  CacheableWrapperFactory::registerType(DSCode::CacheableFloat,
                                        "CacheableFloat",
                                        CacheableFloatWrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableInt16,
                                        "CacheableInt16",
                                        CacheableInt16Wrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableInt32,
                                        "CacheableInt32",
                                        CacheableInt32Wrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableInt64,
                                        "CacheableInt64",
                                        CacheableInt64Wrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableASCIIString,
                                        "CacheableString",
                                        CacheableStringWrapper::create, true);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableString, "CacheableUnicodeString",
      CacheableUnicodeStringWrapper::create, true);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableASCIIStringHuge, "CacheableHugeString",
      CacheableHugeStringWrapper::create, true);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableStringHuge, "CacheableHugeUnicodeString",
      CacheableHugeUnicodeStringWrapper::create, true);
  CacheableWrapperFactory::registerType(DSCode::CacheableCharacter,
                                        "CacheableCharacter",
                                        CacheableWideCharWrapper::create, true);

  // Register other builtin cacheables
  CacheableWrapperFactory::registerType(DSCode::CacheableHashMap,
                                        "CacheableHashMap",
                                        CacheableHashMapWrapper::create, false);
  CacheableWrapperFactory::registerType(DSCode::CacheableHashSet,
                                        "CacheableHashSet",
                                        CacheableHashSetWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableHashTable, "CacheableHashTable",
      CacheableHashTableWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableIdentityHashMap, "CacheableIdentityHashMap",
      CacheableIdentityHashMapWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableLinkedHashSet, "CacheableLinkedHashSet",
      CacheableLinkedHashSetWrapper::create, false);
  CacheableWrapperFactory::registerType(DSCode::CacheableBytes,
                                        "CacheableBytes",
                                        CacheableBytesWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableDoubleArray, "CacheableDoubleArray",
      CacheableDoubleArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableFloatArray, "CacheableFloatArray",
      CacheableFloatArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableInt16Array, "CacheableInt16Array",
      CacheableInt16ArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableInt32Array, "CacheableInt32Array",
      CacheableInt32ArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableInt64Array, "CacheableInt64Array",
      CacheableInt64ArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableNullString, "CacheableNullString",
      CacheableNullStringWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableObjectArray, "CacheableObjectArray",
      CacheableObjectArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableStringArray, "CacheableStringArray",
      CacheableStringArrayWrapper::create, false);
  CacheableWrapperFactory::registerType(DSCode::CacheableVector,
                                        "CacheableVector",
                                        CacheableVectorWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableArrayList, "CacheableArrayList",
      CacheableArrayListWrapper::create, false);
  CacheableWrapperFactory::registerType(
      DSCode::CacheableLinkedList, "CacheableLinkedList",
      CacheableLinkedListWrapper::create, false);
  CacheableWrapperFactory::registerType(DSCode::CacheableStack,
                                        "CacheableStack",
                                        CacheableStackWrapper::create, false);
}

}  // namespace CacheableHelper

#endif  // GEODE_INTEGRATION_TEST_BUILTINCACHEABLEWRAPPERS_H_
