|
26 | 26 | #include "iceberg/catalog/rest/json_serde_internal.h" |
27 | 27 | #include "iceberg/catalog/rest/types.h" |
28 | 28 | #include "iceberg/partition_spec.h" |
| 29 | +#include "iceberg/schema.h" |
29 | 30 | #include "iceberg/result.h" |
30 | 31 | #include "iceberg/sort_order.h" |
31 | 32 | #include "iceberg/table_identifier.h" |
@@ -1380,4 +1381,99 @@ INSTANTIATE_TEST_SUITE_P( |
1380 | 1381 | return info.param.test_name; |
1381 | 1382 | }); |
1382 | 1383 |
|
| 1384 | +// Helper: empty schema and specs for scan response tests that don't need partition parsing. |
| 1385 | +static Schema EmptySchema() { return Schema({}, 0); } |
| 1386 | +static std::unordered_map<int32_t, std::shared_ptr<PartitionSpec>> EmptySpecs() { return {}; } |
| 1387 | + |
| 1388 | +// --- PlanTableScanResponse --- |
| 1389 | + |
| 1390 | +TEST(PlanTableScanResponseFromJsonTest, SubmittedStatusMissingOptionalFields) { |
| 1391 | + // "submitted" response: only status and plan-id, no tasks |
| 1392 | + auto json = nlohmann::json::parse( |
| 1393 | + R"({"status":"submitted","plan-id":"abc-123"})"); |
| 1394 | + auto result = PlanTableScanResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1395 | + ASSERT_THAT(result, IsOk()); |
| 1396 | + EXPECT_EQ(result->plan_status, "submitted"); |
| 1397 | + EXPECT_EQ(result->plan_id, "abc-123"); |
| 1398 | + EXPECT_TRUE(result->plan_tasks.empty()); |
| 1399 | + EXPECT_TRUE(result->file_scan_tasks.empty()); |
| 1400 | + EXPECT_TRUE(result->delete_files.empty()); |
| 1401 | +} |
| 1402 | + |
| 1403 | +TEST(PlanTableScanResponseFromJsonTest, CompletedStatusWithPlanTasks) { |
| 1404 | + // "completed" response with plan-tasks but no file-scan-tasks |
| 1405 | + auto json = nlohmann::json::parse( |
| 1406 | + R"({"status":"completed","plan-id":"abc-123","plan-tasks":["task-1","task-2"],"delete-files":[],"file-scan-tasks":[]})"); |
| 1407 | + auto result = PlanTableScanResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1408 | + ASSERT_THAT(result, IsOk()); |
| 1409 | + EXPECT_EQ(result->plan_status, "completed"); |
| 1410 | + EXPECT_EQ(result->plan_id, "abc-123"); |
| 1411 | + ASSERT_EQ(result->plan_tasks.size(), 2); |
| 1412 | + EXPECT_EQ(result->plan_tasks[0], "task-1"); |
| 1413 | + EXPECT_EQ(result->plan_tasks[1], "task-2"); |
| 1414 | +} |
| 1415 | + |
| 1416 | +TEST(PlanTableScanResponseFromJsonTest, MissingRequiredStatus) { |
| 1417 | + auto json = nlohmann::json::parse(R"({"plan-id":"abc-123"})"); |
| 1418 | + auto result = PlanTableScanResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1419 | + ASSERT_THAT(result, IsError(ErrorKind::kJsonParseError)); |
| 1420 | + EXPECT_THAT(result, HasErrorMessage("Missing 'status'")); |
| 1421 | +} |
| 1422 | + |
| 1423 | +TEST(PlanTableScanResponseFromJsonTest, MissingPlanIdDefaultsToEmptyForFailedStatus) { |
| 1424 | + // plan-id is optional for non-submitted/completed statuses |
| 1425 | + auto json = nlohmann::json::parse(R"({"status":"failed"})"); |
| 1426 | + auto result = PlanTableScanResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1427 | + ASSERT_THAT(result, IsOk()); |
| 1428 | + EXPECT_TRUE(result->plan_id.empty()); |
| 1429 | +} |
| 1430 | + |
| 1431 | +// --- FetchPlanningResultResponse --- |
| 1432 | + |
| 1433 | +TEST(FetchPlanningResultResponseFromJsonTest, SubmittedStatusNoTasks) { |
| 1434 | + auto json = nlohmann::json::parse(R"({"status":"submitted"})"); |
| 1435 | + auto result = FetchPlanningResultResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1436 | + ASSERT_THAT(result, IsOk()); |
| 1437 | + EXPECT_EQ(result->plan_status.ToString(), "submitted"); |
| 1438 | + EXPECT_TRUE(result->plan_tasks.empty()); |
| 1439 | + EXPECT_TRUE(result->file_scan_tasks.empty()); |
| 1440 | + EXPECT_TRUE(result->delete_files.empty()); |
| 1441 | +} |
| 1442 | + |
| 1443 | +TEST(FetchPlanningResultResponseFromJsonTest, CompletedStatusWithPlanTasks) { |
| 1444 | + auto json = nlohmann::json::parse( |
| 1445 | + R"({"status":"completed","plan-tasks":["task-1"],"delete-files":[],"file-scan-tasks":[]})"); |
| 1446 | + auto result = FetchPlanningResultResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1447 | + ASSERT_THAT(result, IsOk()); |
| 1448 | + EXPECT_EQ(result->plan_status.ToString(), "completed"); |
| 1449 | + ASSERT_EQ(result->plan_tasks.size(), 1); |
| 1450 | + EXPECT_EQ(result->plan_tasks[0], "task-1"); |
| 1451 | +} |
| 1452 | + |
| 1453 | +TEST(FetchPlanningResultResponseFromJsonTest, MissingRequiredStatus) { |
| 1454 | + auto json = nlohmann::json::parse(R"({})"); |
| 1455 | + auto result = FetchPlanningResultResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1456 | + ASSERT_THAT(result, IsError(ErrorKind::kJsonParseError)); |
| 1457 | + EXPECT_THAT(result, HasErrorMessage("Missing 'status'")); |
| 1458 | +} |
| 1459 | + |
| 1460 | +// --- FetchScanTasksResponse --- |
| 1461 | + |
| 1462 | +TEST(FetchScanTasksResponseFromJsonTest, WithPlanTasksOnly) { |
| 1463 | + auto json = nlohmann::json::parse( |
| 1464 | + R"({"plan-tasks":["task-1","task-2"],"delete-files":[],"file-scan-tasks":[]})"); |
| 1465 | + auto result = FetchScanTasksResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1466 | + ASSERT_THAT(result, IsOk()); |
| 1467 | + ASSERT_EQ(result->plan_tasks.size(), 2); |
| 1468 | + EXPECT_EQ(result->plan_tasks[0], "task-1"); |
| 1469 | + EXPECT_TRUE(result->file_scan_tasks.empty()); |
| 1470 | +} |
| 1471 | + |
| 1472 | +TEST(FetchScanTasksResponseFromJsonTest, AllFieldsMissing) { |
| 1473 | + // Both plan-tasks and file-scan-tasks absent → Validate() should fail |
| 1474 | + auto json = nlohmann::json::parse(R"({})"); |
| 1475 | + auto result = FetchScanTasksResponseFromJson(json, EmptySpecs(), EmptySchema()); |
| 1476 | + ASSERT_THAT(result, IsError(ErrorKind::kValidationFailed)); |
| 1477 | +} |
| 1478 | + |
1383 | 1479 | } // namespace iceberg::rest |
0 commit comments