Skip to content

test: add test for test coverage#442

Open
lucasfang wants to merge 8 commits into
alibaba:mainfrom
lucasfang:dev4
Open

test: add test for test coverage#442
lucasfang wants to merge 8 commits into
alibaba:mainfrom
lucasfang:dev4

Conversation

@lucasfang

@lucasfang lucasfang commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Linked issue: close #xxx

This change adds targeted unit tests that close concrete coverage gaps identified from the
LCOV report. It is test-only: no production code is modified. Every case locks down a real
behavioral contract, boundary condition, or previously-uncovered error/default branch rather
than repeating an already-covered happy path.

The added tests fall into two areas:

  • Common utilities — error/stringification and failure paths that upper layers rely on:

    • Status::CodeAsString mapping for every StatusCode (including the out-of-range default
      and the instance overload), and Status::Abort fatal-exit behavior.
    • FileTypeUtils::ToString mapping, plus a .tmp unwrap boundary that must not unwrap.
    • Arrow memory-pool adaptor out-of-memory conversion for both Allocate and Reallocate,
      covering the underlying pool returning nullptr and throwing std::bad_alloc.
    • Logging: full severity mapping (including the default branch), glog file-sink write-to-disk,
      and custom logger-creator registration.
    • Block compression factory creation from CompressOptions (case-insensitive codec names,
      unsupported name rejected) and from BlockCompressionType (declared-but-unimplemented LZO
      hits the default branch).
  • Variant subsystem — boundary and error paths of type access, JSON rendering, shredding
    schema inference, shredded write/reassembly round-trips, and the shredding read-plan factory:

    • GenericVariant type-info accessor, type-mismatch rejection of the typed getters, and the
      primitive width branches of ValueSize.
    • VariantJsonUtils control-char escaping, negative-year dates, timestamp fraction/floor-div
      edges, and fixed zone-offset parsing (valid and invalid forms).
    • variant_get casts: UUID-to-string only, Java-style float/double stringification, date
      source, missing cast executor, all scalar Arrow builders, and object-to-list rejection.
    • InferVariantShreddingSchema object/array merges, variant-null handling, depth limit,
      scalar leaf types, long/decimal merge widening and overflow fallback, and cardinality drop.
    • VariantAccessUtils access-spec parsing (malformed descriptions rejected) and file-field
      clipping (unprunable/unshredded/missing-metadata/narrow-to-requested-keys).
    • VariantShreddingReadPlanFactory full-variant reassembly, unshredded value fallback, null
      metadata, shredded typed extraction, nested-variant rebuild with type-mismatch, and
      schema-evolution column absence.
    • variant_shredding round-trips for byte/short/float/binary/date typed columns, timestamp
      schema parsing and reassembly, ScalarSchemaToArrowType, and invalid-schema rejection.

Tests

  • src/paimon/common/utils/status_test.cpp: TestCodeAsString, StatusDeathTest.TestAbort.
  • src/paimon/common/utils/file_type_test.cpp: TestToString; new .tmp boundary case in
    TestInvalidTempWrapperFallsBackToOriginalName.
  • src/paimon/common/utils/arrow/mem_utils_test.cpp: TestAllocateOutOfMemory,
    TestReallocateOutOfMemory (with a FailingMemoryPool helper).
  • src/paimon/common/logging/logging_test.cpp: TestLogAllSeverities,
    TestGlogWritesLogFileToDisk, TestRegisterCustomLoggerCreator.
  • src/paimon/common/compression/block_compression_factory_test.cpp:
    TestCreateFromCompressOptions, TestCreateFromCompressionType.
  • src/paimon/common/data/variant/generic_variant_test.cpp: GetTypeInfoReturnsHeaderBits,
    TypedGettersRejectMismatchedTypes, ValueSizeCoversAllPrimitiveWidths.
  • src/paimon/common/data/variant/variant_json_utils_test.cpp: AppendEscapedJsonControlChars,
    DateToStringNegativeYear, TimestampToStringEdgeCases, ZoneOffsetParsing.
  • src/paimon/common/data/variant/variant_get_test.cpp: UuidSourceCastsToStringOnly,
    FloatingPointToStringMatchesJava, DateSource, MissingCastExecutorYieldsNull,
    ScalarArrowBuilders, ListFromNonArrayIsNull.
  • src/paimon/common/data/variant/infer_variant_shredding_schema_test.cpp:
    MergeObjectsWithDisjointFields, VariantNullSamplesAndFields, ArraysMerge,
    ArrayBeyondDepthLimitStaysVariant, ScalarLeafTypes, LargeIntegerAndDecimalMerging,
    LongMergedWithIntegralDecimalStaysLong, SmallFractionalDecimalPrecisionAdjusted,
    DecimalMergeOverflowFallsToVariant, ObjectWithAllRareFieldsStaysUnshredded.
  • src/paimon/common/data/variant/variant_access_utils_test.cpp (new file):
    ParseAccessSpecsRejectsNonProjection, ParseAccessSpecsRejectsMalformedDescription,
    ParseAccessSpecsRoundTripsBuildMetadata, ClipRejectsNonStructFileField,
    ClipUnprunablePathsReturnFileUnchanged, ClipUnshreddedFileFieldReturnedUnchanged,
    ClipMissingMetadataFails, ClipNarrowsToRequestedKeys.
  • src/paimon/common/data/variant/variant_shredding_read_plan_factory_test.cpp (new file):
    FullVariantReadOfShreddedFile, AccessProjectionOnUnshreddedFile,
    AccessProjectionRejectsNullMetadata, AccessProjectionOnShreddedFile,
    NestedVariantColumnAndTypeMismatch, ColumnAbsentInFileSkipped.
  • src/paimon/common/data/variant/variant_shredding_test.cpp: ScalarShreddingIntegerWidths,
    ScalarShreddingFloatAndBinary, ScalarShreddingDate, TimestampSchemaParsing,
    TimestampReassembly, ScalarSchemaToArrowType, InvalidShreddingSchemas.

API and Format

No API, storage format, or protocol change. This PR only adds tests (and one CMake test-source
registration); no headers under include/ and no production sources are modified.

Documentation

No new feature.

Generative AI tooling

Generated-by: Qoder

Copilot AI review requested due to automatic review settings July 22, 2026 07:55

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Adds additional unit tests to increase coverage across common utility components (Status, FileType, Arrow memory adaptor, logging, and compression factory creation paths).

Changes:

  • Add explicit tests for stringification/mapping helpers (Status::CodeAsString, FileTypeUtils::ToString).
  • Add tests for error/default branches (OOM paths in Arrow pool adaptor, unsupported/unknown compression codecs).
  • Extend logging tests to cover severity mapping, glog file sink behavior, and custom logger registration.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
src/paimon/common/utils/status_test.cpp Adds coverage for Status::CodeAsString and Abort death behavior.
src/paimon/common/utils/file_type_test.cpp Adds coverage for FileTypeUtils::ToString and an additional .tmp unwrap edge case.
src/paimon/common/utils/arrow/mem_utils_test.cpp Adds OOM-path coverage for Arrow pool adaptor allocation/reallocation.
src/paimon/common/logging/logging_test.cpp Adds tests around severity logging, glog file output, and custom logger registration.
src/paimon/common/compression/block_compression_factory_test.cpp Adds coverage for factory creation from options/type, including invalid/default branches.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to +37
TEST(FileTypeTest, TestToString) {
ASSERT_EQ(FileTypeUtils::ToString(FileType::kMeta), "meta");
ASSERT_EQ(FileTypeUtils::ToString(FileType::kData), "data");
ASSERT_EQ(FileTypeUtils::ToString(FileType::kBucketIndex), "bucket_index");
ASSERT_EQ(FileTypeUtils::ToString(FileType::kGlobalIndex), "global_index");
ASSERT_EQ(FileTypeUtils::ToString(FileType::kFileIndex), "file_index");
}
Comment on lines +106 to +125
// Save the global glog flags we are about to change so other tests are unaffected.
const bool prev_logtostderr = FLAGS_logtostderr;
const bool prev_timestamp_in_name = FLAGS_timestamp_in_logfile_name;
const int32_t prev_minloglevel = FLAGS_minloglevel;

// A unique, empty directory so the only file inside is the one glog creates for us.
fs::path log_dir = fs::temp_directory_path() /
("paimon_glog_disk_" + std::to_string(RandomNumber(0, 1'000'000'000)));
fs::create_directories(log_dir);
const fs::path base = log_dir / "paimon_demo";

FLAGS_logtostderr = false; // must be false, otherwise glog skips the file sink
FLAGS_timestamp_in_logfile_name = false; // deterministic file name (no time/pid suffix)
FLAGS_minloglevel = google::GLOG_INFO; // do not filter out INFO

if (!google::IsGoogleLoggingInitialized()) {
google::InitGoogleLogging("paimon-log-disk-test");
}
// Force INFO logs to a file under our unique directory.
google::SetLogDestination(google::GLOG_INFO, base.string().c_str());
Comment on lines +165 to +179
// Keep this test last: it installs a process-wide logger creator that cannot be
// unset, so it must not run before tests that rely on the default logger.
TEST(LoggerTest, TestRegisterCustomLoggerCreator) {
g_creator_calls.store(0);
Logger::RegisterLogger([](const std::string& /*path*/) -> std::unique_ptr<Logger> {
g_creator_calls.fetch_add(1);
return std::make_unique<GlogForwardingLogger>();
});

auto logger = Logger::GetLogger("custom_path");
ASSERT_TRUE(logger);
// GetLogger must have gone through the registered creator branch.
ASSERT_EQ(1, g_creator_calls.load());
ASSERT_TRUE(logger->IsLevelEnabled(PAIMON_LOG_LEVEL_INFO));
}
Comment on lines +54 to +56
bool IsLevelEnabled(PaimonLogLevel /*level*/) const override {
return true;
}
Comment on lines +117 to +129
TEST(MemUtilsTest, TestAllocateOutOfMemory) {
uint8_t* ptr = nullptr;

// Underlying pool returns nullptr for a positive size.
auto null_pool =
GetArrowPool(std::make_shared<FailingMemoryPool>(FailingMemoryPool::Mode::kReturnNull));
ASSERT_TRUE(null_pool->Allocate(16, 64, &ptr).IsOutOfMemory());

// Underlying pool throws std::bad_alloc.
auto throw_pool =
GetArrowPool(std::make_shared<FailingMemoryPool>(FailingMemoryPool::Mode::kThrowBadAlloc));
ASSERT_TRUE(throw_pool->Allocate(16, 64, &ptr).IsOutOfMemory());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants