| /* |
| * 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. |
| */ |
| |
| #include <framework/Cluster.h> |
| #include <framework/Gfsh.h> |
| |
| #include <VariousPdxTypes.hpp> |
| #include <future> |
| #include <initializer_list> |
| #include <iostream> |
| #include <memory> |
| #include <thread> |
| |
| #include <gtest/gtest.h> |
| |
| #include <geode/Cache.hpp> |
| #include <geode/PoolManager.hpp> |
| #include <geode/RegionFactory.hpp> |
| #include <geode/RegionShortcut.hpp> |
| #include <geode/TypeRegistry.hpp> |
| |
| namespace { |
| |
| using apache::geode::client::Cache; |
| using apache::geode::client::CacheableInt32; |
| using apache::geode::client::CacheServerException; |
| using apache::geode::client::HashMapOfCacheable; |
| using apache::geode::client::Region; |
| using apache::geode::client::RegionShortcut; |
| using apache::geode::client::TypeFactoryMethodPdx; |
| |
| using PdxTests::PdxTypes1; |
| using PdxTests::PdxTypes10; |
| using PdxTests::PdxTypes2; |
| using PdxTests::PdxTypes3; |
| using PdxTests::PdxTypes4; |
| using PdxTests::PdxTypes5; |
| using PdxTests::PdxTypes6; |
| using PdxTests::PdxTypes7; |
| using PdxTests::PdxTypes8; |
| using PdxTests::PdxTypes9; |
| |
| template <int32_t Index, class PdxType> |
| struct PdxTypesHelper { |
| static constexpr int32_t index = Index; |
| using type = PdxType; |
| }; |
| |
| using PdxTypesHelper1 = PdxTypesHelper<1, PdxTypes1>; |
| using PdxTypesHelper2 = PdxTypesHelper<2, PdxTypes2>; |
| using PdxTypesHelper3 = PdxTypesHelper<3, PdxTypes3>; |
| using PdxTypesHelper4 = PdxTypesHelper<4, PdxTypes4>; |
| using PdxTypesHelper5 = PdxTypesHelper<5, PdxTypes5>; |
| using PdxTypesHelper6 = PdxTypesHelper<6, PdxTypes6>; |
| using PdxTypesHelper7 = PdxTypesHelper<7, PdxTypes7>; |
| using PdxTypesHelper8 = PdxTypesHelper<8, PdxTypes8>; |
| using PdxTypesHelper9 = PdxTypesHelper<9, PdxTypes9>; |
| using PdxTypesHelper10 = PdxTypesHelper<10, PdxTypes10>; |
| |
| std::shared_ptr<Region> setupRegion(Cache &cache) { |
| auto region = cache.createRegionFactory(RegionShortcut::PROXY) |
| .setPoolName("default") |
| .create("region"); |
| |
| return region; |
| } |
| |
| void registerPdxTypes(Cache &cache, |
| const std::initializer_list<TypeFactoryMethodPdx> |
| &typeFactoryMethodPdxList) { |
| auto &pdxTypeRegistry = cache.getTypeRegistry(); |
| |
| for (const auto &typeFactoryMethodPdx : typeFactoryMethodPdxList) { |
| pdxTypeRegistry.registerPdxType(typeFactoryMethodPdx); |
| } |
| } |
| |
| void setupPdxTypes(Cache &cache) { |
| registerPdxTypes( |
| cache, |
| {PdxTypes1::createDeserializable, PdxTypes2::createDeserializable, |
| PdxTypes3::createDeserializable, PdxTypes4::createDeserializable, |
| PdxTypes5::createDeserializable, PdxTypes6::createDeserializable, |
| PdxTypes7::createDeserializable, PdxTypes8::createDeserializable, |
| PdxTypes9::createDeserializable, PdxTypes10::createDeserializable}); |
| } |
| |
| HashMapOfCacheable setupMap() { |
| HashMapOfCacheable map; |
| map.emplace(CacheableInt32::create(PdxTypesHelper1::index), |
| std::make_shared<PdxTypesHelper1::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper2::index), |
| std::make_shared<PdxTypesHelper2::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper3::index), |
| std::make_shared<PdxTypesHelper3::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper4::index), |
| std::make_shared<PdxTypesHelper4::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper5::index), |
| std::make_shared<PdxTypesHelper5::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper6::index), |
| std::make_shared<PdxTypesHelper6::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper7::index), |
| std::make_shared<PdxTypesHelper7::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper8::index), |
| std::make_shared<PdxTypesHelper8::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper9::index), |
| std::make_shared<PdxTypesHelper9::type>()); |
| map.emplace(CacheableInt32::create(PdxTypesHelper10::index), |
| std::make_shared<PdxTypesHelper10::type>()); |
| return map; |
| } |
| |
| template <class T> |
| void assert_eq(HashMapOfCacheable &expected, HashMapOfCacheable &actual) { |
| const auto key = CacheableInt32::create(T::index); |
| ASSERT_TRUE( |
| std::dynamic_pointer_cast<typename T::type>(expected[key]) |
| ->equals(std::dynamic_pointer_cast<typename T::type>(actual[key]))) |
| << "Expected key " << key->value() << " with value of type " |
| << typeid(typename T::type).name() << " to be equal."; |
| } |
| |
| void assert_eq(HashMapOfCacheable &expected, HashMapOfCacheable &actual) { |
| ASSERT_EQ(expected.size(), actual.size()); |
| |
| assert_eq<PdxTypesHelper1>(expected, actual); |
| assert_eq<PdxTypesHelper2>(expected, actual); |
| assert_eq<PdxTypesHelper3>(expected, actual); |
| assert_eq<PdxTypesHelper4>(expected, actual); |
| assert_eq<PdxTypesHelper5>(expected, actual); |
| assert_eq<PdxTypesHelper6>(expected, actual); |
| assert_eq<PdxTypesHelper7>(expected, actual); |
| assert_eq<PdxTypesHelper8>(expected, actual); |
| assert_eq<PdxTypesHelper9>(expected, actual); |
| assert_eq<PdxTypesHelper10>(expected, actual); |
| } |
| |
| template <class Key, class... Tail> |
| std::vector<Key> to_keys(std::unordered_map<Key, Tail...> map) { |
| std::vector<Key> keys; |
| keys.reserve(map.size()); |
| for (const auto &entry : map) { |
| keys.push_back(entry.first); |
| } |
| return keys; |
| } |
| |
| template <class Container> |
| void localDestroy(Region ®ion, const Container keys) { |
| for (const auto &key : keys) { |
| region.localDestroy(key); |
| } |
| } |
| |
| /** |
| * Port of testThinClientPutGetAll |
| */ |
| TEST(RegionPutGetAllTest, variousPdxTypes) { |
| Cluster cluster{LocatorCount{1}, ServerCount{2}}; |
| cluster.getGfsh() |
| .create() |
| .region() |
| .withName("region") |
| .withType("REPLICATE") |
| .execute(); |
| |
| auto cache = cluster.createCache(); |
| auto region = setupRegion(cache); |
| |
| setupPdxTypes(cache); |
| |
| auto putAllMap = setupMap(); |
| auto keys = to_keys(putAllMap); |
| |
| // TODO - Understand: Put one tests putAll doesn't fail for existing entry? |
| region->put(putAllMap.cbegin()->first, putAllMap.cbegin()->second); |
| |
| region->putAll(putAllMap); |
| |
| // TODO - Understand: Clear local cache to force fetch from server? |
| localDestroy(*region, keys); |
| |
| auto getAllMap = region->getAll(keys); |
| |
| assert_eq(putAllMap, getAllMap); |
| } |
| |
| TEST(RegionPutGetAllTest, nullValue) { |
| Cluster cluster{LocatorCount{1}, ServerCount{2}}; |
| cluster.getGfsh() |
| .create() |
| .region() |
| .withName("region") |
| .withType("REPLICATE") |
| .execute(); |
| |
| auto cache = cluster.createCache(); |
| auto region = setupRegion(cache); |
| |
| setupPdxTypes(cache); |
| |
| HashMapOfCacheable map; |
| |
| // Add a null value |
| map.emplace(CacheableInt32::create(PdxTypesHelper1::index), |
| std::shared_ptr<PdxTypesHelper1::type>()); |
| |
| auto keys = to_keys(map); |
| |
| ASSERT_THROW(region->putAll(map), CacheServerException); |
| } |
| |
| } // namespace |