This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch master
in repository ffmpeg.

commit 2d9c8a93820680b550bf73509438cd998d631380
Author:     marcos ashton <[email protected]>
AuthorDate: Thu Apr 9 15:24:48 2026 +0100
Commit:     michaelni <[email protected]>
CommitDate: Tue Apr 28 16:17:47 2026 +0000

    tests/fate/libavutil: add FATE test for buffer
    
    Test av_buffer_alloc, av_buffer_allocz, av_buffer_create with
    custom free callback, AV_BUFFER_FLAG_READONLY, av_buffer_ref,
    av_buffer_is_writable, av_buffer_get_ref_count,
    av_buffer_make_writable, av_buffer_realloc (including from NULL),
    av_buffer_replace (including with NULL), av_buffer_pool
    init/get/uninit cycle, av_buffer_pool_init2 with custom alloc
    and pool_free callbacks, av_buffer_pool_buffer_get_opaque, and
    OOM paths via av_max_alloc.
    
    Coverage for libavutil/buffer.c: 0.00% -> 90.19%
    
    Remaining uncovered lines are mutex init failures and
    secondary allocation failure paths.
---
 .forgejo/CODEOWNERS      |   2 +
 libavutil/Makefile       |   1 +
 libavutil/tests/buffer.c | 251 +++++++++++++++++++++++++++++++++++++++++++++++
 tests/fate/libavutil.mak |   4 +
 tests/ref/fate/buffer    |  57 +++++++++++
 5 files changed, 315 insertions(+)

diff --git a/.forgejo/CODEOWNERS b/.forgejo/CODEOWNERS
index b9b7b107a9..96bee17dff 100644
--- a/.forgejo/CODEOWNERS
+++ b/.forgejo/CODEOWNERS
@@ -232,7 +232,9 @@ doc/.* @GyanD
 # tests
 # =====
 tests/checkasm/riscv/.* @Courmisch
+libavutil/tests/buffer.* @MarcosAsh
 tests/ref/.*drawvg.* @ayosec
+tests/ref/fate/buffer @MarcosAsh
 tests/ref/fate/sub-mcc.* @programmerjake
 
 # Forgejo
diff --git a/libavutil/Makefile b/libavutil/Makefile
index 38e08a3d5d..903e5cdcad 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -263,6 +263,7 @@ TESTPROGS = adler32                                         
            \
             base64                                                      \
             blowfish                                                    \
             bprint                                                      \
+            buffer                                                      \
             cast5                                                       \
             camellia                                                    \
             channel_layout                                              \
diff --git a/libavutil/tests/buffer.c b/libavutil/tests/buffer.c
new file mode 100644
index 0000000000..b6e67befb4
--- /dev/null
+++ b/libavutil/tests/buffer.c
@@ -0,0 +1,251 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "libavutil/buffer.h"
+#include "libavutil/mem.h"
+
+static int custom_free_called;
+static int pool_free_called;
+static int pool_alloc2_called;
+
+static void custom_free(void *opaque, uint8_t *data)
+{
+    custom_free_called = 1;
+    av_free(data);
+}
+
+static AVBufferRef *pool_alloc2(void *opaque, size_t size)
+{
+    pool_alloc2_called = 1;
+    return av_buffer_alloc(size);
+}
+
+static void pool_free_cb(void *opaque)
+{
+    pool_free_called = 1;
+}
+
+int main(void)
+{
+    AVBufferRef *buf, *buf2;
+    AVBufferPool *pool;
+
+    /* av_buffer_alloc */
+    printf("Testing av_buffer_alloc()\n");
+    buf = av_buffer_alloc(64);
+    if (buf) {
+        printf("alloc: size=%zu data=%s\n", buf->size, buf->data ? "set" : 
"null");
+        printf("writable: %d\n", av_buffer_is_writable(buf));
+        printf("refcount: %d\n", av_buffer_get_ref_count(buf));
+        av_buffer_unref(&buf);
+        printf("after unref: %s\n", buf == NULL ? "null" : "leaked");
+    }
+
+    /* av_buffer_allocz */
+    printf("\nTesting av_buffer_allocz()\n");
+    buf = av_buffer_allocz(16);
+    if (buf) {
+        int zeroed = 1;
+        for (int i = 0; i < 16; i++)
+            if (buf->data[i] != 0) zeroed = 0;
+        printf("allocz: zeroed=%s\n", zeroed ? "yes" : "no");
+        av_buffer_unref(&buf);
+    }
+
+    /* av_buffer_create with custom free */
+    printf("\nTesting av_buffer_create()\n");
+    {
+        uint8_t *data = av_malloc(32);
+        if (data) {
+            custom_free_called = 0;
+            buf = av_buffer_create(data, 32, custom_free, NULL, 0);
+            if (buf) {
+                printf("create: size=%zu\n", buf->size);
+                printf("opaque: %s\n",
+                       av_buffer_get_opaque(buf) == NULL ? "null" : "set");
+                av_buffer_unref(&buf);
+                printf("custom_free called: %s\n",
+                       custom_free_called ? "yes" : "no");
+            } else {
+                av_free(data);
+            }
+        }
+    }
+
+    /* av_buffer_create with READONLY flag */
+    printf("\nTesting AV_BUFFER_FLAG_READONLY\n");
+    {
+        uint8_t *data = av_malloc(16);
+        if (data) {
+            buf = av_buffer_create(data, 16, custom_free, NULL,
+                                   AV_BUFFER_FLAG_READONLY);
+            if (buf) {
+                printf("readonly writable: %d\n", av_buffer_is_writable(buf));
+                av_buffer_unref(&buf);
+            } else {
+                av_free(data);
+            }
+        }
+    }
+
+    /* av_buffer_ref and refcounting */
+    printf("\nTesting av_buffer_ref()\n");
+    buf = av_buffer_alloc(32);
+    if (buf) {
+        buf->data[0] = 0xAB;
+        buf2 = av_buffer_ref(buf);
+        if (buf2) {
+            printf("ref: refcount=%d\n", av_buffer_get_ref_count(buf));
+            printf("shared data: %s\n",
+                   buf2->data[0] == 0xAB ? "yes" : "no");
+            printf("writable after ref: %d\n", av_buffer_is_writable(buf));
+            av_buffer_unref(&buf2);
+            printf("refcount after unref: %d\n", av_buffer_get_ref_count(buf));
+            printf("writable after unref: %d\n", av_buffer_is_writable(buf));
+        }
+        av_buffer_unref(&buf);
+    }
+
+    /* av_buffer_make_writable */
+    printf("\nTesting av_buffer_make_writable()\n");
+    buf = av_buffer_alloc(16);
+    if (buf) {
+        buf->data[0] = 0xCD;
+        buf2 = av_buffer_ref(buf);
+        if (buf2) {
+            int ret = av_buffer_make_writable(&buf2);
+            printf("make_writable ret: %d\n", ret >= 0);
+            printf("data preserved: %s\n",
+                   buf2->data[0] == 0xCD ? "yes" : "no");
+            printf("now writable: %d\n", av_buffer_is_writable(buf2));
+            printf("original still valid: %s\n",
+                   buf->data[0] == 0xCD ? "yes" : "no");
+            av_buffer_unref(&buf2);
+        }
+        av_buffer_unref(&buf);
+    }
+
+    /* av_buffer_realloc */
+    printf("\nTesting av_buffer_realloc()\n");
+    buf = av_buffer_alloc(16);
+    if (buf) {
+        memset(buf->data, 0xEF, 16);
+        av_buffer_realloc(&buf, 32);
+        if (buf) {
+            printf("realloc: size=%zu\n", buf->size);
+            printf("data preserved: %s\n",
+                   buf->data[0] == 0xEF ? "yes" : "no");
+        }
+        av_buffer_unref(&buf);
+    }
+    /* realloc from NULL */
+    buf = NULL;
+    av_buffer_realloc(&buf, 8);
+    printf("realloc from null: %s\n", buf ? "OK" : "FAIL");
+    av_buffer_unref(&buf);
+
+    /* av_buffer_replace */
+    printf("\nTesting av_buffer_replace()\n");
+    buf = av_buffer_alloc(8);
+    buf2 = av_buffer_alloc(8);
+    if (buf && buf2) {
+        buf->data[0] = 0x11;
+        buf2->data[0] = 0x22;
+        av_buffer_replace(&buf, buf2);
+        printf("replace: data=0x%02x\n", buf->data[0]);
+        printf("refcount: %d\n", av_buffer_get_ref_count(buf2));
+    }
+    av_buffer_unref(&buf);
+    av_buffer_unref(&buf2);
+
+    /* replace with NULL */
+    buf = av_buffer_alloc(8);
+    if (buf) {
+        av_buffer_replace(&buf, NULL);
+        printf("replace with null: %s\n", buf == NULL ? "OK" : "FAIL");
+    }
+
+    /* av_buffer_pool */
+    printf("\nTesting av_buffer_pool()\n");
+    pool = av_buffer_pool_init(64, NULL);
+    if (pool) {
+        buf = av_buffer_pool_get(pool);
+        if (buf) {
+            printf("pool get: size=%zu\n", buf->size);
+            av_buffer_unref(&buf);
+        }
+        /* get again -- should reuse the released buffer */
+        buf = av_buffer_pool_get(pool);
+        if (buf) {
+            printf("pool reuse: size=%zu\n", buf->size);
+            av_buffer_unref(&buf);
+        }
+        av_buffer_pool_uninit(&pool);
+        printf("pool uninit: %s\n", pool == NULL ? "OK" : "FAIL");
+    }
+
+    /* av_buffer_pool_init2 with custom alloc and pool_free callbacks */
+    printf("\nTesting av_buffer_pool_init2()\n");
+    pool_alloc2_called = 0;
+    pool_free_called = 0;
+    pool = av_buffer_pool_init2(64, NULL, pool_alloc2, pool_free_cb);
+    if (pool) {
+        buf = av_buffer_pool_get(pool);
+        if (buf) {
+            printf("pool2 get: size=%zu\n", buf->size);
+            printf("alloc2 called: %s\n", pool_alloc2_called ? "yes" : "no");
+            printf("pool_buffer_get_opaque: %s\n",
+                   av_buffer_pool_buffer_get_opaque(buf) == NULL ? "null" : 
"set");
+            av_buffer_unref(&buf);
+        }
+        av_buffer_pool_uninit(&pool);
+        printf("pool_free called: %s\n", pool_free_called ? "yes" : "no");
+    }
+
+    /* OOM paths via av_max_alloc */
+    printf("\nTesting OOM paths\n");
+    av_max_alloc(1);
+    buf = av_buffer_alloc(64);
+    printf("alloc OOM: %s\n", buf ? "FAIL" : "OK");
+    av_buffer_unref(&buf);
+    buf = av_buffer_allocz(64);
+    printf("allocz OOM: %s\n", buf ? "FAIL" : "OK");
+    av_buffer_unref(&buf);
+    pool = av_buffer_pool_init(64, NULL);
+    printf("pool init OOM: %s\n", pool ? "FAIL" : "OK");
+    av_buffer_pool_uninit(&pool);
+    av_max_alloc(INT_MAX);
+
+    buf = av_buffer_alloc(16);
+    if (buf) {
+        av_max_alloc(1);
+        buf2 = av_buffer_ref(buf);
+        printf("ref OOM: %s\n", buf2 ? "FAIL" : "OK");
+        av_buffer_unref(&buf2);
+        printf("realloc OOM: %s\n",
+               av_buffer_realloc(&buf, 1024) < 0 ? "OK" : "FAIL");
+        av_max_alloc(INT_MAX);
+        av_buffer_unref(&buf);
+    }
+
+    return 0;
+}
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 12143bc248..af78a803e5 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -47,6 +47,10 @@ FATE_LIBAVUTIL += fate-bprint
 fate-bprint: libavutil/tests/bprint$(EXESUF)
 fate-bprint: CMD = run libavutil/tests/bprint$(EXESUF)
 
+FATE_LIBAVUTIL += fate-buffer
+fate-buffer: libavutil/tests/buffer$(EXESUF)
+fate-buffer: CMD = run libavutil/tests/buffer$(EXESUF)
+
 FATE_LIBAVUTIL += fate-cpu
 fate-cpu: libavutil/tests/cpu$(EXESUF)
 fate-cpu: CMD = runecho libavutil/tests/cpu$(EXESUF) $(CPUFLAGS:%=-c%) 
$(THREADS:%=-t%)
diff --git a/tests/ref/fate/buffer b/tests/ref/fate/buffer
new file mode 100644
index 0000000000..5c2946babf
--- /dev/null
+++ b/tests/ref/fate/buffer
@@ -0,0 +1,57 @@
+Testing av_buffer_alloc()
+alloc: size=64 data=set
+writable: 1
+refcount: 1
+after unref: null
+
+Testing av_buffer_allocz()
+allocz: zeroed=yes
+
+Testing av_buffer_create()
+create: size=32
+opaque: null
+custom_free called: yes
+
+Testing AV_BUFFER_FLAG_READONLY
+readonly writable: 0
+
+Testing av_buffer_ref()
+ref: refcount=2
+shared data: yes
+writable after ref: 0
+refcount after unref: 1
+writable after unref: 1
+
+Testing av_buffer_make_writable()
+make_writable ret: 1
+data preserved: yes
+now writable: 1
+original still valid: yes
+
+Testing av_buffer_realloc()
+realloc: size=32
+data preserved: yes
+realloc from null: OK
+
+Testing av_buffer_replace()
+replace: data=0x22
+refcount: 2
+replace with null: OK
+
+Testing av_buffer_pool()
+pool get: size=64
+pool reuse: size=64
+pool uninit: OK
+
+Testing av_buffer_pool_init2()
+pool2 get: size=64
+alloc2 called: yes
+pool_buffer_get_opaque: null
+pool_free called: yes
+
+Testing OOM paths
+alloc OOM: OK
+allocz OOM: OK
+pool init OOM: OK
+ref OOM: OK
+realloc OOM: OK

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to