Implementation:NVIDIA DALI C API Legacy Tests
| Knowledge Sources | |
|---|---|
| Domains | Data_Pipeline, C_API |
| Last Updated | 2026-02-08 16:00 GMT |
Overview
The C API legacy test suite validates the correctness of all major functions in the DALI v1 C API, including pipeline creation, external input feeding, output retrieval, checkpointing, and cross-backend data transfers.
Description
This file contains a comprehensive Google Test suite for the legacy DALI C API defined in dali/c_api.h. It belongs to the NVIDIA DALI data loading library and exercises the C API through typed tests parameterized over CPU and GPU backends. The test fixture CApiTest is templated on CPUBackend and GPUBackend, allowing each test case to run against both execution paths.
The test suite covers: pipeline creation from serialized protobuf (FileReader-based and ExternalSource-based pipelines), single-allocation and multi-allocation external input feeding, variable batch size support, cross-backend data feeding (CPU data to GPU operator and vice versa), force-copy and force-no-copy semantics, output copying with daliOutputCopy and daliOutputCopySamples, executor metadata retrieval, operator backend inspection, external source details querying, deserialization validation, declared output dtype and ndim, max batch size, and full checkpointing round-trip.
Each test creates a pipeline using helper functions (GetTestPipeline, GetExternalSourcePipeline), serializes it, then uses the C API to create a parallel pipeline and compares their outputs element-by-element via the ComparePipelinesOutputs helper.
Usage
Use this test suite when verifying that changes to the legacy C API or underlying Pipeline implementation do not introduce regressions. Run the tests as part of the DALI build system's test target to validate pipeline lifecycle, data feeding, output correctness, and checkpointing behavior on both CPU and GPU.
Code Reference
Source Location
- Repository: NVIDIA_DALI
- File: dali/c_api/c_api_test.cc
- Lines: 1-1168
Signature
template<typename Backend>
class CApiTest : public ::testing::Test { ... };
using Backends = ::testing::Types<CPUBackend, GPUBackend>;
TYPED_TEST_SUITE(CApiTest, Backends);
// Key typed tests:
TYPED_TEST(CApiTest, GetOutputNameTest);
TYPED_TEST(CApiTest, FileReaderPipe);
TYPED_TEST(CApiTest, FileReaderDefaultPipe);
TYPED_TEST(CApiTest, ExternalSourceSingleAllocPipe);
TYPED_TEST(CApiTest, ExternalSourceSingleAllocVariableBatchSizePipe);
TYPED_TEST(CApiTest, ExternalSourceMultipleAllocPipe);
TYPED_TEST(CApiTest, ExternalSourceSingleAllocDifferentBackendsTest);
TYPED_TEST(CApiTest, ExternalSourceMultipleAllocDifferentBackendsTest);
TYPED_TEST(CApiTest, TestExecutorMeta);
TYPED_TEST(CApiTest, UseCopyKernel);
TYPED_TEST(CApiTest, ForceNoCopyFail);
TYPED_TEST(CApiTest, ForceCopy);
TYPED_TEST(CApiTest, ForceNoCopy);
TYPED_TEST(CApiTest, daliOutputCopySamples);
TYPED_TEST(CApiTest, IsDeserializableTest);
// Non-typed tests:
TEST(CApiTest, CpuOnlyTest);
TEST(CApiTest, GetBackendTest);
TEST(CApiTest, GetESDetailsTest);
TEST(CApiTest, GetMaxBatchSizeTest);
TEST(CApiTest, GetDeclaredOutputDtypeNdimTest);
TEST(CApiTest, CheckpointingTest);
Import
#include <gtest/gtest.h>
#include "dali/c_api.h"
#include "dali/pipeline/pipeline.h"
#include "dali/test/dali_test_config.h"
#include "dali/test/tensor_test_utils.h"
I/O Contract
Inputs
| Name | Type | Required | Description |
|---|---|---|---|
| Backend template parameter | CPUBackend or GPUBackend | Yes | Selects which backend to test |
| DALI test data (DALI_EXTRA_PATH) | Filesystem | Yes | JPEG images and file lists for FileReader tests |
| input_shape | TensorListShape<> | Yes | Hardcoded tensor shapes for ExternalSource tests |
Outputs
| Name | Type | Description |
|---|---|---|
| Test assertions | GTest EXPECT/ASSERT | Pass/fail results comparing C API outputs against baseline Pipeline outputs |
Usage Examples
FileReader Pipeline Test Pattern
// Create a test pipeline with FileReader and Resize operators
auto pipe_ptr = GetTestPipeline<TypeParam>(true, output_device_);
auto serialized = pipe_ptr->SerializeToProtobuf();
pipe_ptr->Build();
for (int i = 0; i < prefetch_queue_depth; i++)
pipe_ptr->Run();
// Create equivalent pipeline via C API
daliPipelineHandle handle;
daliCreatePipeline(&handle, serialized.c_str(), serialized.size(),
batch_size, num_thread, device_id_,
false, prefetch_queue_depth,
prefetch_queue_depth, prefetch_queue_depth, false);
daliPrefetchUniform(&handle, prefetch_queue_depth);
// Compare outputs
ComparePipelinesOutputs<TypeParam>(handle, *pipe_ptr);
daliDeletePipeline(&handle);
Checkpointing Test Pattern
auto handle1 = CreateCheckpointingTestPipe();
// Run for several iterations
for (int i = 0; i < 3; i++) {
daliRun(&handle1);
daliOutput(&handle1);
}
// Save and restore checkpoint
daliExternalContextCheckpoint ctx{};
char *cpt;
size_t n;
daliGetSerializedCheckpoint(&handle1, &ctx, &cpt, &n);
auto handle2 = CreateCheckpointingTestPipe();
daliExternalContextCheckpoint restored{};
daliRestoreFromSerializedCheckpoint(&handle2, cpt, n, &restored);
// Verify results match
double result1, result2;
daliRun(&handle1); daliOutput(&handle1);
daliOutputCopy(&handle1, &result1, 0, CPU, 0, DALI_ext_default);
daliRun(&handle2); daliOutput(&handle2);
daliOutputCopy(&handle2, &result2, 0, CPU, 0, DALI_ext_default);
EXPECT_EQ(result1, result2);