| 78 | } // namespace |
| 79 | |
| 80 | TEST_P(MemoryCapExceededTest, DISABLED_singleDriver) { |
| 81 | // Executes a plan with a single driver thread and query memory limit that |
| 82 | // forces it to throw MEM_CAP_EXCEEDED exception. Verifies that the error |
| 83 | // message contains all the details expected. |
| 84 | |
| 85 | vector_size_t size = 1'024; |
| 86 | // This limit ensures that only the Aggregation Operator fails. |
| 87 | constexpr int64_t kMaxBytes = 5LL << 20; // 5MB |
| 88 | // We look for these lines separately, since their order can change (not sure |
| 89 | // why). |
| 90 | std::vector<std::string> expectedTexts = { |
| 91 | "Exceeded memory pool cap of 5.00MB with max 5.00MB when requesting " |
| 92 | "2.00MB, memory manager cap is 8.00GB, requestor " |
| 93 | "'op.2.0.0.Aggregation' with current usage 3.70MB"}; |
| 94 | std::vector<std::string> expectedDetailedTexts = { |
| 95 | "node.1 usage 1.00MB reserved 1.00MB peak 1.00MB", |
| 96 | "op.1.0.0.FilterProject usage 12.00KB reserved 1.00MB peak 12.00KB", |
| 97 | "node.2 usage 4.00MB reserved 4.00MB peak 4.00MB", |
| 98 | "op.2.0.0.Aggregation usage 3.70MB reserved 4.00MB peak 3.70MB", |
| 99 | "Top 2 leaf memory pool usages:"}; |
| 100 | |
| 101 | std::vector<RowVectorPtr> data; |
| 102 | for (auto i = 0; i < 100; ++i) { |
| 103 | data.push_back(makeRowVector({ |
| 104 | makeFlatVector<int64_t>( |
| 105 | size, [&i](auto row) { return row + (i * 1000); }), |
| 106 | makeFlatVector<int64_t>(size, [](auto row) { return row + 3; }), |
| 107 | })); |
| 108 | } |
| 109 | |
| 110 | // Plan created to allow multiple operators to show up in the top 3 memory |
| 111 | // usage list in the error message. |
| 112 | auto plan = PlanBuilder() |
| 113 | .values(data) |
| 114 | .project({"c0", "c0 + c1"}) |
| 115 | .singleAggregation({"c0"}, {"sum(p1)"}) |
| 116 | .orderBy({"c0"}, false) |
| 117 | .planNode(); |
| 118 | auto queryCtx = core::QueryCtx::create(executor_.get()); |
| 119 | queryCtx->testingOverrideMemoryPool( |
| 120 | memory::memoryManager()->addRootPool(queryCtx->queryId(), kMaxBytes)); |
| 121 | CursorParameters params; |
| 122 | params.planNode = plan; |
| 123 | params.queryCtx = queryCtx; |
| 124 | params.maxDrivers = 1; |
| 125 | try { |
| 126 | readCursor(params, [](Task*) {}); |
| 127 | FAIL() << "Expected a MEM_CAP_EXCEEDED RuntimeException."; |
| 128 | } catch (const BoltException& e) { |
| 129 | const auto errorMessage = e.message(); |
| 130 | for (const auto& expectedText : expectedTexts) { |
| 131 | ASSERT_TRUE(errorMessage.find(expectedText) != std::string::npos) |
| 132 | << "Expected error message to contain '" << expectedText |
| 133 | << "', but received '" << errorMessage << "'."; |
| 134 | } |
| 135 | for (const auto& expectedText : expectedDetailedTexts) { |
| 136 | LOG(ERROR) << expectedText; |
| 137 | if (!GetParam()) { |
nothing calls this directly
no test coverage detected