diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 6d8c11e4..2409cd2b 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -25,7 +25,8 @@ set(LIBKQUEUE_TEST_SOURCES
     test.c
     timer.c
     user.c
-    vnode.c)
+    vnode.c
+    write.c)
 if(UNIX)
   list(APPEND LIBKQUEUE_TEST_SOURCES
        proc.c
diff --git a/test/common.h b/test/common.h
index 69e20431..fbf16fb4 100644
--- a/test/common.h
+++ b/test/common.h
@@ -112,6 +112,7 @@ void test_kqueue(struct test_context *);
 void test_evfilt_read(struct test_context *);
 void test_evfilt_signal(struct test_context *);
 void test_evfilt_vnode(struct test_context *);
+void test_evfilt_write(struct test_context *);
 void test_evfilt_timer(struct test_context *);
 void test_evfilt_proc(struct test_context *);
 #ifdef EVFILT_USER
diff --git a/test/main.c b/test/main.c
index e5c0dece..da80eb4e 100644
--- a/test/main.c
+++ b/test/main.c
@@ -169,6 +169,10 @@ main(int argc, char **argv)
           .ut_func = test_evfilt_vnode,
           .ut_end = INT_MAX },
 #endif
+        { .ut_name = "write",
+          .ut_enabled = 1,
+          .ut_func = test_evfilt_write,
+          .ut_end = INT_MAX },
 #ifdef EVFILT_USER
         { .ut_name = "user",
           .ut_enabled = 1,
diff --git a/test/write.c b/test/write.c
new file mode 100644
index 00000000..46224a1b
--- /dev/null
+++ b/test/write.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2024 Arran Cudbard-Bell <a.cudbardb@freeradius.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "common.h"
+
+
+/** Test if we can setup an event to write to a regular file
+ *
+ * Setting up a write event on a regular file doesn't make much sense
+ * but it is allowed by kqueue, so check we exhibit similar behaviour.
+ */
+void
+test_kevent_write_regular_file(struct test_context *ctx)
+{
+    struct kevent kev, ret[1];
+    int fd;
+
+    fd = open(ctx->testfile, O_CREAT | O_WRONLY);
+    if (fd < 0)
+        abort();
+
+    EV_SET(&kev, fd, EVFILT_WRITE, EV_ADD, 0, 0, &fd);
+    kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL));
+    kevent_get(ret, NUM_ELEMENTS(ret), ctx->kqfd, 1);
+
+    /* File should appear immediately writable */
+    kevent_get(NULL, 0, ctx->kqfd, 1);
+    kevent_cmp(&kev, ret);
+    if (write(fd, "test", 4) != 4) {
+        printf("failed writing to set file: %s", strerror(errno));
+        abort();
+    }
+
+    /* ...should still be writable */
+    kevent_get(NULL, 0, ctx->kqfd, 1);
+    kevent_cmp(&kev, ret);
+
+    kev.flags = EV_DELETE;
+    kevent_rv_cmp(0, kevent(ctx->kqfd, &kev, 1, NULL, 0, NULL));
+
+    close(fd);
+    unlink(ctx->testfile);
+}
+
+void
+test_evfilt_write(struct test_context *ctx)
+{
+    char *tmpdir = getenv("TMPDIR");
+    if (tmpdir == NULL)
+#ifdef __ANDROID__
+        tmpdir = "/data/local/tmp";
+#else
+        tmpdir = "/tmp";
+#endif
+
+    snprintf(ctx->testfile, sizeof(ctx->testfile), "%s/kqueue-test%d.tmp",
+            tmpdir, testing_make_uid());
+
+    test(kevent_write_regular_file, ctx);
+}