diff --git a/libavutil/Makefile b/libavutil/Makefile
index eb8de1dfbc..4526ec80ca 100644
--- a/libavutil/Makefile
+++ b/libavutil/Makefile
@@ -269,6 +269,7 @@ TESTPROGS = adler32                                                     \
             uuid                                                        \
             xtea                                                        \
             tea                                                         \
+            writer                                                      \
 
 TESTPROGS-$(HAVE_THREADS)            += cpu_init
 TESTPROGS-$(HAVE_LZO1X_999_COMPRESS) += lzo
diff --git a/libavutil/tests/.gitignore b/libavutil/tests/.gitignore
index 87895912f5..7559e7a24c 100644
--- a/libavutil/tests/.gitignore
+++ b/libavutil/tests/.gitignore
@@ -51,3 +51,4 @@
 /utf8
 /uuid
 /xtea
+/writer
diff --git a/libavutil/tests/writer.c b/libavutil/tests/writer.c
new file mode 100644
index 0000000000..fdb8c4d703
--- /dev/null
+++ b/libavutil/tests/writer.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2019 Nicolas George
+ *
+ * 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 <stdio.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "libavutil/avassert.h"
+#include "libavutil/error.h"
+#include "libavutil/log.h"
+#include "libavutil/writer.h"
+
+/* see 69bd73b3ff873abb43de9db062b04425de153643 */
+
+/* AVWriter with only get_buffer/advance_buffer */
+
+static char *getbuf_get_buffer(AVWriter wr, size_t min_size, size_t *size);
+static void getbuf_advance_buffer(AVWriter wr, size_t size);
+
+AV_WRITER_DEFINE_METHODS(static, Getbuf, getbuf) {
+    .self_size        = sizeof(AVWriterMethods),
+    .name             = "Getbuf",
+    .get_buffer       = getbuf_get_buffer,
+    .advance_buffer   = getbuf_advance_buffer,
+};
+
+static char *getbuf_get_buffer(AVWriter wr, size_t min_size, size_t *size)
+{
+    AVBufWriter *bwr = wr.obj;
+
+    av_assert0(getbuf_check(wr));
+    *size = bwr->size - 1 - bwr->pos;
+    return bwr->buf + bwr->pos;
+}
+
+static void getbuf_advance_buffer(AVWriter wr, size_t size)
+{
+    AVBufWriter *bwr = wr.obj;
+
+    bwr->pos += size;
+    bwr->buf[bwr->pos] = 0;
+}
+
+/* AVWriter with only write */
+
+static void write_write(AVWriter wr, const char *data, size_t size);
+
+AV_WRITER_DEFINE_METHODS(static, Write, write) {
+    .self_size        = sizeof(AVWriterMethods),
+    .name             = "Write",
+    .write            = write_write,
+};
+
+static void write_write(AVWriter wr, const char *data, size_t size)
+{
+    AVBufWriter *bwr = wr.obj;
+
+    av_assert0(write_check(wr));
+    size = FFMIN(bwr->size - 1 - bwr->pos, size);
+    memcpy(bwr->buf + bwr->pos, data, size);
+    bwr->pos += size;
+    bwr->buf[bwr->pos] = 0;
+}
+
+/* AVWriter with only vprintf */
+
+static void vprintf_vprintf(AVWriter wr, const char *fmt, va_list va);
+
+AV_WRITER_DEFINE_METHODS(static, Vprintf, vprintf) {
+    .self_size        = sizeof(AVWriterMethods),
+    .name             = "Vprintf",
+    .vprintf          = vprintf_vprintf,
+};
+
+static void vprintf_vprintf(AVWriter wr, const char *fmt, va_list va)
+{
+    AVBufWriter *bwr = wr.obj;
+    int ret;
+
+    av_assert0(vprintf_check(wr));
+    ret = vsnprintf(bwr->buf + bwr->pos, bwr->size - bwr->pos, fmt, va);
+    if (ret > 0)
+        bwr->pos += ret;
+}
+
+/* Tests */
+
+static void stress_writer(AVWriter wr)
+{
+    av_writer_add_chars(wr, '*', 72);
+    av_writer_add_chars(wr, '\n', 1);
+    av_writer_print(wr, "Stressing the writer\n");
+    av_writer_printf(wr, "Answer: %d\n", 42);
+    av_writer_printf(wr, "Question: %0600d * %0600d\n", 6, 9); /* > sizeof(AVBPrint) */
+    av_writer_add_chars(wr, '*', 72);
+    av_writer_add_chars(wr, '\n', 1);
+    av_writer_write(wr, "\0Bonus track!\n", 14);
+}
+
+static void test_buf_writer_small(void)
+{
+    char buf[1024];
+    AVWriter wr = av_buf_writer_array(buf);
+    stress_writer(wr);
+    printf("AVBufWriter/1024: [%s]\n", buf);
+}
+
+static void test_buf_writer_large(void)
+{
+    char buf[8192];
+    AVWriter wr = av_buf_writer_array(buf);
+    stress_writer(wr);
+    printf("AVDynbufWriter/8192: [%s]\n", buf);
+}
+
+static void test_dynbuf_writer(void)
+{
+    AVWriter wr = av_dynbuf_writer();
+    char *data;
+    size_t size, i;
+    int ret;
+
+    stress_writer(wr);
+    data = av_dynbuf_writer_get_buffer(wr, 100, &size);
+    ret = snprintf(data, size, "Some more?\n");
+    av_dynbuf_writer_advance_buffer(wr, ret);
+    ret = av_writer_get_error(wr, 0);
+    if (ret < 0) {
+        av_log(NULL, AV_LOG_ERROR, "DynbufWriter (%zd chars): %s\n", size, av_err2str(ret));
+        return;
+    }
+    data = av_dynbuf_writer_get_data(wr, &size);
+    for (i = 0; i < size; i++)
+        if (data[i] == 0)
+            data[i] = '@'; /* avoid confusing diff */
+    printf("AVDynbufWriter (%zd chars): [", size);
+    fwrite(data, 1, size, stdout);
+    printf("]\n");
+    av_dynbuf_writer_finalize(wr, NULL, NULL);
+}
+
+static void test_writer_limited(const char *name, const AVWriterMethods *methods)
+{
+    char buf[8192];
+    AVBufWriter bwr = { sizeof(AVBufWriter), buf, sizeof(buf), 0 };
+    AVWriter wr = { methods, &bwr };
+    stress_writer(wr);
+    printf("%s: [%s]\n", name, buf);
+}
+
+static void test_writer_get_buffer(void)
+{
+    test_writer_limited("get_buffer", getbuf_get_methods());
+}
+
+static void test_writer_write(void)
+{
+    test_writer_limited("write", write_get_methods());
+}
+
+static void test_writer_vprintf(void)
+{
+    test_writer_limited("vprintf", vprintf_get_methods());
+}
+
+int main(int argc, char **argv)
+{
+    if (1) test_buf_writer_small();
+    if (1) test_buf_writer_large();
+    if (1) test_dynbuf_writer();
+    if (1) test_writer_get_buffer();
+    if (1) test_writer_write();
+    if (1) test_writer_vprintf();
+    return 0;
+}
diff --git a/tests/fate/libavutil.mak b/tests/fate/libavutil.mak
index 80153f4395..a9dcc9ec87 100644
--- a/tests/fate/libavutil.mak
+++ b/tests/fate/libavutil.mak
@@ -175,6 +175,10 @@ fate-uuid: libavutil/tests/uuid$(EXESUF)
 fate-uuid: CMD = run libavutil/tests/uuid$(EXESUF)
 fate-uuid: CMP = null
 
+FATE_LIBAVUTIL += fate-writer
+fate-writer: libavutil/tests/writer$(EXESUF)
+fate-writer: CMD = run libavutil/tests/writer$(EXESUF)
+
 FATE_LIBAVUTIL += $(FATE_LIBAVUTIL-yes)
 FATE-$(CONFIG_AVUTIL) += $(FATE_LIBAVUTIL)
 fate-libavutil: $(FATE_LIBAVUTIL)
diff --git a/tests/ref/fate/writer b/tests/ref/fate/writer
new file mode 100644
index 0000000000..3068d83a4a
--- /dev/null
+++ b/tests/ref/fate/writer
@@ -0,0 +1,36 @@
+AVBufWriter/1024: [************************************************************************
+Stressing the writer
+Answer: 42
+Question: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 * 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000]
+AVDynbufWriter/8192: [************************************************************************
+Stressing the writer
+Answer: 42
+Question: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 * 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009
+************************************************************************
+]
+AVDynbufWriter (1417 chars): [************************************************************************
+Stressing the writer
+Answer: 42
+Question: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 * 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009
+************************************************************************
+@Bonus track!
+Some more?
+]
+get_buffer: [************************************************************************
+Stressing the writer
+Answer: 42
+Question: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 * 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009
+************************************************************************
+]
+write: [************************************************************************
+Stressing the writer
+Answer: 42
+Question: 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006 * 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009
+************************************************************************
+]
+vprintf: [************************************************************************
+Stressing the writer
