From c6bfe2e2f2f6fbe0655d56872085a61e9f0aa640 Mon Sep 17 00:00:00 2001 From: Masha Basmanova Date: Tue, 13 Feb 2024 09:57:25 -0500 Subject: [PATCH] Fix 'out of range in dynamic array' error in Task::toJson --- velox/exec/Task.cpp | 11 +++++---- velox/exec/tests/TaskTest.cpp | 42 +++++++++++++++++++++++++++-------- 2 files changed, 38 insertions(+), 15 deletions(-) diff --git a/velox/exec/Task.cpp b/velox/exec/Task.cpp index fd5addd7af67..364ba829fb4e 100644 --- a/velox/exec/Task.cpp +++ b/velox/exec/Task.cpp @@ -2154,14 +2154,13 @@ folly::dynamic Task::toJson() const { obj["plan"] = planFragment_.planNode->toString(true, true); } - folly::dynamic driverObj = folly::dynamic::array; - int index = 0; - for (auto& driver : drivers_) { - if (driver) { - driverObj[index++] = driver->toJson(); + folly::dynamic drivers = folly::dynamic::object; + for (auto i = 0; i < drivers_.size(); ++i) { + if (drivers_[i] != nullptr) { + drivers[i] = drivers_[i]->toJson(); } } - obj["drivers"] = driverObj; + obj["drivers"] = drivers; if (auto buffers = bufferManager_.lock()) { if (auto buffer = buffers->getBufferIfExists(taskId_)) { diff --git a/velox/exec/tests/TaskTest.cpp b/velox/exec/tests/TaskTest.cpp index c64252719084..37c9e5618395 100644 --- a/velox/exec/tests/TaskTest.cpp +++ b/velox/exec/tests/TaskTest.cpp @@ -502,14 +502,7 @@ class TaskTest : public HiveConnectorTestBase { } }; -TEST_F(TaskTest, wrongPlanNodeForSplit) { - auto connectorSplit = std::make_shared( - "test", - "file:/tmp/abc", - facebook::velox::dwio::common::FileFormat::DWRF, - 0, - 100); - +TEST_F(TaskTest, toJson) { auto plan = PlanBuilder() .tableScan(ROW({"a", "b"}, {INTEGER(), DOUBLE()})) .project({"a * a", "b + b"}) @@ -525,11 +518,42 @@ TEST_F(TaskTest, wrongPlanNodeForSplit) { task->toString(), "{Task task-1 (task-1)Plan: -- Project\n\n drivers:\n"); ASSERT_EQ( folly::toPrettyJson(task->toJson()), - "{\n \"concurrentSplitGroups\": 1,\n \"drivers\": [],\n \"exchangeClientByPlanNode\": {},\n \"groupedPartitionedOutput\": false,\n \"id\": \"task-1\",\n \"noMoreOutputBuffers\": false,\n \"numDriversPerSplitGroup\": 0,\n \"numDriversUngrouped\": 0,\n \"numFinishedDrivers\": 0,\n \"numRunningDrivers\": 0,\n \"numRunningSplitGroups\": 0,\n \"numThreads\": 0,\n \"numTotalDrivers\": 0,\n \"onThreadSince\": \"0\",\n \"partitionedOutputConsumed\": false,\n \"pauseRequested\": false,\n \"plan\": \"-- Project[expressions: (p0:INTEGER, multiply(ROW[\\\"a\\\"],ROW[\\\"a\\\"])), (p1:DOUBLE, plus(ROW[\\\"b\\\"],ROW[\\\"b\\\"]))] -> p0:INTEGER, p1:DOUBLE\\n -- TableScan[table: hive_table] -> a:INTEGER, b:DOUBLE\\n\",\n \"shortId\": \"task-1\",\n \"state\": \"Running\",\n \"terminateRequested\": false\n}"); + "{\n \"concurrentSplitGroups\": 1,\n \"drivers\": {},\n \"exchangeClientByPlanNode\": {},\n \"groupedPartitionedOutput\": false,\n \"id\": \"task-1\",\n \"noMoreOutputBuffers\": false,\n \"numDriversPerSplitGroup\": 0,\n \"numDriversUngrouped\": 0,\n \"numFinishedDrivers\": 0,\n \"numRunningDrivers\": 0,\n \"numRunningSplitGroups\": 0,\n \"numThreads\": 0,\n \"numTotalDrivers\": 0,\n \"onThreadSince\": \"0\",\n \"partitionedOutputConsumed\": false,\n \"pauseRequested\": false,\n \"plan\": \"-- Project[expressions: (p0:INTEGER, multiply(ROW[\\\"a\\\"],ROW[\\\"a\\\"])), (p1:DOUBLE, plus(ROW[\\\"b\\\"],ROW[\\\"b\\\"]))] -> p0:INTEGER, p1:DOUBLE\\n -- TableScan[table: hive_table] -> a:INTEGER, b:DOUBLE\\n\",\n \"shortId\": \"task-1\",\n \"state\": \"Running\",\n \"terminateRequested\": false\n}"); ASSERT_EQ( folly::toPrettyJson(task->toShortJson()), "{\n \"id\": \"task-1\",\n \"numFinishedDrivers\": 0,\n \"numRunningDrivers\": 0,\n \"numThreads\": 0,\n \"numTotalDrivers\": 0,\n \"pauseRequested\": false,\n \"shortId\": \"task-1\",\n \"state\": \"Running\",\n \"terminateRequested\": false\n}"); + task->start(2); + + ASSERT_NO_THROW(task->toJson()); + ASSERT_NO_THROW(task->toShortJson()); + + task->noMoreSplits("0"); + waitForTaskCompletion(task.get()); + + ASSERT_NO_THROW(task->toJson()); + ASSERT_NO_THROW(task->toShortJson()); +} + +TEST_F(TaskTest, wrongPlanNodeForSplit) { + auto connectorSplit = std::make_shared( + "test", + "file:/tmp/abc", + facebook::velox::dwio::common::FileFormat::DWRF, + 0, + 100); + + auto plan = PlanBuilder() + .tableScan(ROW({"a", "b"}, {INTEGER(), DOUBLE()})) + .project({"a * a", "b + b"}) + .planFragment(); + + auto task = Task::create( + "task-1", + std::move(plan), + 0, + std::make_shared(driverExecutor_.get())); + // Add split for the source node. task->addSplit("0", exec::Split(folly::copy(connectorSplit)));