diff --git a/tests/unit/location/test_location.cc b/tests/unit/location/test_location.cc index 5eaeb65270..2801da3e45 100644 --- a/tests/unit/location/test_location.cc +++ b/tests/unit/location/test_location.cc @@ -42,7 +42,7 @@ //@HEADER */ -#include "test_location_message.h" +#include "test_location_common.h" namespace vt { namespace tests { namespace unit { @@ -275,52 +275,15 @@ TYPED_TEST_P(TestLocationRoute, test_entity_cache_hits){ auto const nb_rounds = 3; auto nb_received = 0; - // the protocol is defined as eager for short and unserialized messages - bool const is_eager = std::is_same::value; - // register entity and count received messages if (my_node == home) { vt::theLocMan()->virtual_loc->registerEntity( entity, my_node, [&](vt::BaseMessage* msg){ nb_received++; } ); } - vt::theCollective()->barrier(); - for (int iter = 0; iter < nb_rounds; ++iter) { - if (my_node not_eq home) { - // route entity message - auto msg = vt::makeMessage(entity, my_node); - vt::theLocMan()->virtual_loc->routeMsg(entity, home, msg); - - // check for cache updates - bool is_entity_cached = locat::isCached(entity); - #if DEBUG_LOCATION_TESTS - fmt::print( - "iter:{}, rank {}: route_test: entityID={}, home_node={}, {} message of {} bytes, is in cache ? {}.\n", - iter, my_node, msg->data_, msg->from_, (is_long ? "long" : "short"), sizeof(*msg), is_entity_cached - ); - #endif - - if (not is_eager) { - // On non eager case: the location is first explicitly resolved - // and then the message is routed and the cache updated. - // Hence, the entity is not yet registered in cache after the - // first send, but will be for next ones. - EXPECT_TRUE(iter < 1 or is_entity_cached); - } else { - // On eager case: the message is directly routed to the - // implicitly resolved location. - // Thus the cache is not updated in this case. - EXPECT_FALSE(is_entity_cached); - } - } else { - // The entity should be registered in the cache of the home node, - // regardless of the protocol (eager or not) - EXPECT_TRUE(locat::isCached(entity)); - } - // wait for the termination of all ranks - vt::theCollective()->barrier(); - } + // check cache consistency for the given entity + locat::verifyCacheConsistency(entity, my_node, home, home, nb_rounds); // finalize if (my_node == home) { @@ -330,7 +293,57 @@ TYPED_TEST_P(TestLocationRoute, test_entity_cache_hits){ } } -REGISTER_TYPED_TEST_CASE_P(TestLocationRoute, test_route_entity, test_entity_cache_hits); +TYPED_TEST_P(TestLocationRoute, test_entity_cache_migrated_entity){ + + auto const nb_nodes = vt::theContext()->getNumNodes(); + auto const my_node = vt::theContext()->getNode(); + auto const entity = locat::arbitrary_entity; + auto const home = 0; + auto const new_home = 3; + auto const nb_rounds = 3; + auto nb_received = 0; + + // register entity + if (my_node == home) { + vt::theLocMan()->virtual_loc->registerEntity(entity, my_node); + } + vt::theCollective()->barrier(); + + if (my_node == home) { + // migrate entity: unregister it but keep its id in cache + vt::theLocMan()->virtual_loc->entityMigrated(entity, new_home); + EXPECT_TRUE(locat::isCached(entity)); + } else if (my_node == new_home) { + // receive migrated entity: register it and keep in cache + vt::theLocMan()->virtual_loc->registerEntityMigrated( + entity, my_node, [entity,&nb_received](vt::BaseMessage* in_msg) { + #if DEBUG_LOCATION_TESTS + fmt::print( + "rank:{}: a message arrived to me for a migrated entity {}.\n", + vt::theContext()->getNode(), entity + ); + #endif + nb_received++; + } + ); + EXPECT_TRUE(locat::isCached(entity)); + } + + // check cache consistency for the given entity + locat::verifyCacheConsistency(entity, my_node, home, new_home, nb_rounds); + + // finalize + if (my_node == new_home) { + vt::theLocMan()->virtual_loc->unregisterEntity(entity); + auto const min_expected_ack = (nb_nodes - 2) * nb_rounds; + EXPECT_TRUE(nb_received >= min_expected_ack); + EXPECT_FALSE(locat::isCached(entity)); + } +} + +REGISTER_TYPED_TEST_CASE_P( + TestLocationRoute, test_route_entity, test_entity_cache_hits, test_entity_cache_migrated_entity +); INSTANTIATE_TYPED_TEST_CASE_P(Message, TestLocationRoute, locat::MsgType); }}} // end namespace vt::tests::unit \ No newline at end of file diff --git a/tests/unit/location/test_location_message.h b/tests/unit/location/test_location_common.h similarity index 67% rename from tests/unit/location/test_location_message.h rename to tests/unit/location/test_location_common.h index e78c9b8ee8..b7d0098cd7 100644 --- a/tests/unit/location/test_location_message.h +++ b/tests/unit/location/test_location_common.h @@ -121,7 +121,61 @@ void routeTestHandler(EntityMsg* msg) { } // check if the given entity is in the node cache -bool isCached(int const entity) { return vt::theLocMan()->virtual_loc->isCached(entity); }; +bool isCached(int const entity) { + return vt::theLocMan()->virtual_loc->isCached(entity); +}; + +// check if the given entity should be stored in cache or not +// depending on the situation: +// - eager or non eager protocol +// - current iteration +// - (previous) home node or not +template +void verifyCacheConsistency( + int const entity, vt::NodeType const my_node, + vt::NodeType const home, vt::NodeType const new_home, int const nb_rounds +) { + + vt::theCollective()->barrier(); + // the protocol is defined as eager for short and unserialized messages + bool const is_eager = std::is_same::value; + + for (int iter = 0; iter < nb_rounds; ++iter) { + if (my_node not_eq home) { + // route entity message + auto msg = vt::makeMessage(entity, my_node); + vt::theLocMan()->virtual_loc->routeMsg(entity, home, msg); + + // check for cache updates + bool is_entity_cached = isCached(entity); + #if DEBUG_LOCATION_TESTS + fmt::print( + "iter:{}, rank {}: route_test: entityID={}, home_node={}, {} message of {} bytes, is in cache ? {}.\n", + iter, my_node, msg->data_, msg->from_, (is_long ? "long" : "short"), sizeof(*msg), is_entity_cached + ); + #endif + + if (not is_eager) { + // On non eager case: the location is first explicitly resolved + // and then the message is routed and the cache updated. + // Hence, the entity is not yet registered in cache after the + // first send, but will be for next ones. + EXPECT_TRUE(iter < 1 or is_entity_cached); + } else if(my_node not_eq new_home) { + // On eager case: the message is directly routed to the + // implicitly resolved location. + // Thus the cache is not updated in this case. + EXPECT_FALSE(is_entity_cached); + } + } else { + // The entity should be registered in the cache of the home node, + // regardless of the protocol (eager or not) + EXPECT_TRUE(isCached(entity)); + } + // wait for the termination of all ranks + vt::theCollective()->barrier(); + } +} // message types used for type-parameterized tests using MsgType = testing::Types;