|
21 | 21 | #include "mrc/node/rx_node.hpp" |
22 | 22 | #include "mrc/node/rx_sink.hpp" |
23 | 23 | #include "mrc/node/rx_source.hpp" |
| 24 | +#include "mrc/options/engine_groups.hpp" |
24 | 25 | #include "mrc/options/options.hpp" |
25 | 26 | #include "mrc/options/placement.hpp" |
26 | 27 | #include "mrc/options/topology.hpp" |
27 | 28 | #include "mrc/pipeline/executor.hpp" |
28 | 29 | #include "mrc/pipeline/pipeline.hpp" |
29 | 30 | #include "mrc/runnable/context.hpp" |
30 | 31 | #include "mrc/runnable/launch_options.hpp" |
| 32 | +#include "mrc/runnable/types.hpp" // for EngineType |
31 | 33 | #include "mrc/segment/builder.hpp" |
32 | 34 | #include "mrc/segment/object.hpp" |
| 35 | +#include "mrc/system/device_info.hpp" |
33 | 36 | #include "mrc/utils/string_utils.hpp" |
34 | 37 |
|
35 | 38 | #include <boost/fiber/operations.hpp> |
@@ -789,4 +792,112 @@ TEST_P(ParallelTests, NodeMultiThread) |
789 | 792 | EXPECT_EQ(complete_count, 1); |
790 | 793 | } |
791 | 794 |
|
| 795 | +struct PeExceedsResourcesParams |
| 796 | +{ |
| 797 | + std::string cpu_set; |
| 798 | + std::size_t pe_count; |
| 799 | + std::string bad_node; |
| 800 | + mrc::runnable::EngineType engine_type; |
| 801 | +}; |
| 802 | + |
| 803 | +struct PeExceedsTests : public testing::TestWithParam<PeExceedsResourcesParams> |
| 804 | +{}; |
| 805 | + |
| 806 | +// Run parallel tests for 1, 2 and 4 threads |
| 807 | +INSTANTIATE_TEST_SUITE_P(TestNode, |
| 808 | + PeExceedsTests, |
| 809 | + testing::Values(PeExceedsResourcesParams{"0-9", // cpu set of 10 cores |
| 810 | + 11, // pe count one greater |
| 811 | + "sink", |
| 812 | + mrc::runnable::EngineType::Fiber}, |
| 813 | + PeExceedsResourcesParams{"0-5", // cpu set of 6 cores |
| 814 | + 11, |
| 815 | + "source", |
| 816 | + mrc::runnable::EngineType::Fiber}, |
| 817 | + PeExceedsResourcesParams{"0-3", // cpu set of 4 cores |
| 818 | + 5, // pe lower than cores |
| 819 | + "node", |
| 820 | + mrc::runnable::EngineType::Fiber}, |
| 821 | + PeExceedsResourcesParams{"0-9", // cpu set of 10 cores |
| 822 | + 11, // pe count one greater |
| 823 | + "sink", |
| 824 | + mrc::runnable::EngineType::Thread}, |
| 825 | + PeExceedsResourcesParams{"0-5", // cpu set of 6 cores |
| 826 | + 11, |
| 827 | + "source", |
| 828 | + mrc::runnable::EngineType::Thread}, |
| 829 | + PeExceedsResourcesParams{"0-3", // cpu set of 4 cores |
| 830 | + 5, // pe lower than cores |
| 831 | + "node", |
| 832 | + mrc::runnable::EngineType::Thread})); |
| 833 | + |
| 834 | +TEST_P(PeExceedsTests, PeExceedsResources) |
| 835 | +{ |
| 836 | + const auto test_params = GetParam(); |
| 837 | + |
| 838 | + EXPECT_DEATH_OR_THROW( |
| 839 | + { |
| 840 | + // EXPECT_DEATH Executes this test in a fork, we need to reset the NvmlState singleton which would |
| 841 | + // otherwise reflect the state of the parent process |
| 842 | + mrc::system::DeviceInfo::Reset(); |
| 843 | + auto p = mrc::make_pipeline(); |
| 844 | + |
| 845 | + const std::string cpu_set = test_params.cpu_set; |
| 846 | + const std::size_t pe_count = test_params.pe_count; |
| 847 | + |
| 848 | + auto my_segment = p->make_segment("my_segment", [&](segment::IBuilder& seg) { |
| 849 | + auto source = seg.make_source<int>("src1", [&](rxcpp::subscriber<int>& s) { |
| 850 | + EXPECT_TRUE(false) << "Preflight checks should fail, this should not be " |
| 851 | + "called"; |
| 852 | + }); |
| 853 | + |
| 854 | + auto node = seg.make_node<int>("node", rxcpp::operators::map([&](const int& x) { |
| 855 | + EXPECT_TRUE(false) << "Preflight checks should fail, this should " |
| 856 | + "not be " |
| 857 | + "called"; |
| 858 | + return x; |
| 859 | + })); |
| 860 | + |
| 861 | + auto sink = seg.make_sink<int>( |
| 862 | + "sink", |
| 863 | + [&](const int& x) { |
| 864 | + EXPECT_TRUE(false) << "Preflight checks should fail, this should not be " |
| 865 | + "called"; |
| 866 | + }, |
| 867 | + [&]() { |
| 868 | + EXPECT_TRUE(false) << "Preflight checks should fail, this should not be " |
| 869 | + "called"; |
| 870 | + }); |
| 871 | + |
| 872 | + if (test_params.bad_node == "source") |
| 873 | + { |
| 874 | + source->launch_options().pe_count = pe_count; |
| 875 | + } |
| 876 | + else if (test_params.bad_node == "node") |
| 877 | + { |
| 878 | + node->launch_options().pe_count = pe_count; |
| 879 | + } |
| 880 | + else |
| 881 | + { |
| 882 | + sink->launch_options().pe_count = pe_count; |
| 883 | + } |
| 884 | + |
| 885 | + seg.make_edge(source, node); |
| 886 | + seg.make_edge(node, sink); |
| 887 | + }); |
| 888 | + |
| 889 | + auto options = std::make_unique<Options>(); |
| 890 | + options->topology().user_cpuset(cpu_set); |
| 891 | + options->engine_factories().set_default_engine_type(test_params.engine_type); |
| 892 | + |
| 893 | + Executor exec(std::move(options)); |
| 894 | + exec.register_pipeline(std::move(p)); |
| 895 | + |
| 896 | + exec.start(); |
| 897 | + exec.join(); |
| 898 | + }, |
| 899 | + "A node was destructed which still had dependent connections", |
| 900 | + std::runtime_error); |
| 901 | +} |
| 902 | + |
792 | 903 | } // namespace mrc |
0 commit comments