Skip to content

test(model): cover a failed model-collection growth - #1663

Merged
lusoris merged 1 commit into
masterfrom
port/upstream-1590-model-collection-growth-test
Oct 1, 2026
Merged

lusoris merged 1 commit into
masterfrom
port/upstream-1590-model-collection-growth-test

Conversation

@lusoris

@lusoris lusoris commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Summary

This adds the regression test that the fork was missing for the fix of our upstream Netflix/vmaf PR #1590. No library code changes.

vmaf_model_collection_append() doubles its model array when the eighth slot is taken. Upstream takes its common failure label when that realloc() fails and clears the caller's handle, which loses the collection and its models. The fork already returns -ENOMEM directly and leaves the collection untouched (core/src/model.c), but no test called vmaf_model_collection_append() at all, so a rebase onto upstream's version would have gone unnoticed.

test_model_collection_growth links with -Wl,--wrap=realloc, fails the one realloc() of the model array, and checks three cases on real models loaded from model/vmaf_v0.6.1.json:

  • eight models fill the initial array without growing it;
  • the ninth doubles it once and keeps every member;
  • a failed growth returns -ENOMEM, leaves handle, array, count, capacity and members unchanged, and the rejected model can be appended on retry.

Type

  • feat — new feature
  • fix — bug fix
  • perf — performance improvement
  • refactor — no behavior change
  • docs — documentation only
  • test — test-only
  • build / ci — tooling / infra
  • port — cherry-pick from upstream Netflix/vmaf
  • sycl / cuda / simd — backend-specific

Checklist

  • Commits follow Conventional Commits (the commit-msg hook enforces this).
  • make format && make lint is green locally. Not run in full. Run instead: clang-format --dry-run -Werror on the new file (clean), scripts/ci/tidy-ratchet.py --lane cpu --only core/test/test_model_collection_growth.c (0 warnings in the file), and the pre-commit hook set (passed).
  • Unit tests pass: fast suite on a CPU build, 191 passed, 0 failed, 2 skipped, and on a CUDA build (gcc, nvcc, RTX 4090), 249 passed, 0 failed, 1 skipped; the new test also passes under ASan + UBSan + LeakSanitizer.
  • If I touched any SIMD/GPU code path, I ran /cross-backend-diff and the worst ULP is ≤ 2. None touched.
  • If I touched a feature extractor with SIMD/GPU twins, I either updated every twin or listed the gap under "Known follow-ups" below. None touched.
  • If I added a new .c / .cpp / .cu / .h / .hpp, it has the appropriate license header (see CONTRIBUTING.md).
  • If this is a breaking change, the commit message uses ! or BREAKING CHANGE: and the migration path is documented below.
  • If this PR adds an ADR, the ADR row lives in docs/adr/_index_fragments/<NNNN-slug>.md and the slug is appended to docs/adr/_index_fragments/_order.txt.

Bug-status hygiene (ADR-0165)

  • docs/state.md updated: T-MODEL-COLLECTION-GROWTH-FAILURE-UNTESTED-2026-10-01 under Recently closed.

Netflix golden-data gate (ADR-0024)

  • I did not modify any assertAlmostEqual(...) score in the Netflix golden Python tests.
  • If I believe a golden value must change, I have explained why below AND pinged @lusoris for a CODEOWNERS exception.

Deep-dive deliverables (ADR-0108)

  • Research digest — no digest needed: test-only change.
  • Decision matrix — no alternatives: only-one-way fix already in tree; the test uses the link-time --wrap control the neighbouring ownership tests use.
  • AGENTS.md invariant note — no rebase-sensitive invariants beyond the rebase note below.
  • Reproducer / smoke-test command — pasted below under "Reproducer".
  • CHANGELOG fragment — changelog.d/changed/test-model-collection-growth-failure.md.
  • Rebase note — entry added to docs/rebase-notes.md.

Reproducer

CC=gcc meson setup build-san core -Db_lto=false -Denable_cuda=false -Denable_sycl=false \
  -Denable_float=true -Db_sanitize=address,undefined -Dbuildtype=debugoptimized
ninja -C build-san test/test_model_collection_growth
ASAN_OPTIONS=detect_leaks=1:halt_on_error=1 UBSAN_OPTIONS=halt_on_error=1 \
  build-san/test/test_model_collection_growth
# 3 tests run, 3 passed

Negative control, run locally and not committed: with upstream's *model_collection = NULL put back into the growth branch of vmaf_model_collection_append(), the third case fails with a failed growth lost or changed the existing collection.

Known follow-ups

None. The test is built on Linux with the static archive and without LTO only, because --wrap needs the linker to see the library's reference to realloc; test_registration_partial_copy has the same constraint.

@github-actions github-actions Bot added the type:test Test-only change label Oct 1, 2026
vmaf_model_collection_append() doubles its model array when the eighth
slot is taken. Upstream Netflix/vmaf takes its common failure label when
that realloc() fails and clears the caller's handle, which loses the
collection and its models; the fork returns -ENOMEM directly and leaves
the collection untouched. That is the fix of our upstream PR #1590, and
no test called vmaf_model_collection_append() at all.

test_model_collection_growth links with -Wl,--wrap=realloc, fails the one
realloc() of the model array, and checks on real models that eight
models fill the initial array without growing it, that the ninth doubles
it once and keeps every member, and that a failed growth returns
-ENOMEM, changes nothing, and lets the caller append the rejected model
again. With upstream's "*model_collection = NULL" put back the third
case fails.

No library code changes.
@lusoris
lusoris force-pushed the port/upstream-1590-model-collection-growth-test branch from c8edb32 to 0873165 Compare October 1, 2026 08:15
@lusoris
lusoris merged commit 9af7590 into master Oct 1, 2026
27 of 28 checks passed
@lusoris
lusoris deleted the port/upstream-1590-model-collection-growth-test branch October 1, 2026 08:15
lusoris added a commit that referenced this pull request Oct 1, 2026
Each of the fork's fifteen open Netflix/vmaf pull requests (#1588 to
against the fork's code, with ASan + UBSan builds where the report is
about memory or undefined behaviour.

The fork needs none of the six commits. It carries the fix of every pull
request except the second revision of #1602, which is a score change left
to the maintainer. Three gaps found on the way are in their own pull
requests: #1662 (a negative threshold shift in the scalar adm_cm), #1663
and #1664 (regression tests for #1590 and #1604).

docs/state.md gains seventeen rows under "Confirmed not-affected", each
with the fork file and function, the test, and what was run; the #1604
row is corrected (the tool refuses odd 4:2:0 dimensions for raw input
only). docs/rebase-notes.md says what a sync can skip and what it must
keep. docs/development/known-upstream-bugs.md lists all fifteen pull
requests with the fork's status and records that they are no longer
updated while upstream does not act on them.
lusoris added a commit that referenced this pull request Oct 1, 2026
* docs(state): record the 2026-10-01 upstream reconciliation

Each of the fork's fifteen open Netflix/vmaf pull requests (#1588 to
against the fork's code, with ASan + UBSan builds where the report is
about memory or undefined behaviour.

The fork needs none of the six commits. It carries the fix of every pull
request except the second revision of #1602, which is a score change left
to the maintainer. Three gaps found on the way are in their own pull
requests: #1662 (a negative threshold shift in the scalar adm_cm), #1663
and #1664 (regression tests for #1590 and #1604).

docs/state.md gains seventeen rows under "Confirmed not-affected", each
with the fork file and function, the test, and what was run; the #1604
row is corrected (the tool refuses odd 4:2:0 dimensions for raw input
only). docs/rebase-notes.md says what a sync can skip and what it must
keep. docs/development/known-upstream-bugs.md lists all fifteen pull
requests with the fork's status and records that they are no longer
updated while upstream does not act on them.

* docs(upstream): keep the reconciliation page to the technical status
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:test Test-only change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant