root/regress/lib/libc/open_wmemstream/open_wmemstreamtest.c
/*      $OpenBSD: open_wmemstreamtest.c,v 1.1 2026/05/08 14:37:16 millert Exp $ */

/*
 * Copyright (c) 2011 Martin Pieuchot <mpi@openbsd.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 <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <unistd.h>

#define OFFSET 16384

const wchar_t start[] = { 's', 't', 'a', 'r', 't', 0 };
const wchar_t hello[] = { 'h', 'e', 'l', 'l', 'o', 0 };

int
main(void)
{
        FILE    *fp;
        wchar_t *buf = (wchar_t *)0xff;
        size_t   size = 0;
        off_t    off;
        int      i, failures = 0;

        if ((fp = open_wmemstream(&buf, &size)) == NULL) {
                warn("open_wmemstream failed");
                return (1);
        }

        off = ftello(fp);
        if (off != 0) {
                warnx("ftello failed. (1)");
                failures++;
        }

        if (fflush(fp) != 0) {
                warnx("fflush failed. (2)");
                failures++;
        }

        if (size != 0) {
                warnx("string should be empty. (3)");
                failures++;
        }

        if (buf == (wchar_t *)0xff) {
                warnx("buf not updated. (4)");
                failures++;
        }

        if (fseek(fp, OFFSET, SEEK_SET) != 0) {
                warnx("failed to fseek. (5)");
                failures++;
        }

        if (fwprintf(fp, hello) == EOF) {
                warnx("fwprintf failed. (6)");
                failures++;
        }

        if (fflush(fp) == EOF) {
                warnx("fflush failed. (7)");
                failures++;
        }

        if (size != OFFSET + wcslen(hello)) {
                warnx("failed, size %zu should be %zu. (8)",
                    size, OFFSET + wcslen(hello));
                failures++;
        }

        if (fseek(fp, 0, SEEK_SET) != 0) {
                warnx("failed to fseek. (9)");
                failures++;
        }

        if (fwprintf(fp, start) == EOF) {
                warnx("fwprintf failed. (10)");
                failures++;
        }

        if (fflush(fp) == EOF) {
                warnx("fflush failed. (11)");
                failures++;
        }

        if (size != wcslen(start)) {
                warnx("failed, size %zu should be %zu. (12)",
                    size, wcslen(start));
                failures++;
        }

        /* Needed for sparse files */
        if (wcsncmp(buf, start, wcslen(start)) != 0) {
                char buf[sizeof(start)];
                wcstombs(buf, start, sizeof(buf));
                warnx("failed, buffer didn't start with '%s'. (13)", buf);
                failures++;
        }
        for (i = wcslen(start); i < OFFSET; i++)
                if (buf[i] != '\0') {
                        warnx("failed, buffer non zero (offset %d). (14)", i);
                        failures++;
                        break;
                }

        if (memcmp(buf + OFFSET, hello, wcslen(hello)) != 0) {
                warnx("written string incorrect. (15)");
                failures++;
        }

        /* verify that simply seeking past the end doesn't increase the size */
        if (fseek(fp, 100, SEEK_END) != 0) {
                warnx("failed to fseek. (16)");
                failures++;
        }

        if (fflush(fp) == EOF) {
                warnx("fflush failed. (17)");
                failures++;
        }

        if (size != OFFSET + wcslen(hello)) {
                warnx("failed, size %zu should be %zu. (18)",
                    size, OFFSET + wcslen(hello));
                failures++;
        }

        if (fseek(fp, -1, SEEK_END) != 0) {
                warnx("failed to fseek. (19)");
                failures++;
        }

        if (fseek(fp, 8, SEEK_SET) != 0) {
                warnx("failed to fseek. (20)");
                failures++;
        }

        if (ftell(fp) != 8) {
                warnx("failed seek test. (21)");
                failures++;
        }

        /* Try to seek backward */
        if (fseek(fp, -1, SEEK_CUR) != 0) {
                warnx("failed to fseek. (22)");
                failures++;
        }

        if (ftell(fp) != 7) {
                warnx("failed seeking backward. (23)");
                failures++;
        }

        if (fseek(fp, 5, SEEK_CUR) != 0) {
                warnx("failed to fseek. (24)");
                failures++;
        }

        if (fclose(fp) == EOF) {
                warnx("fclose failed. (25)");
                failures++;
        }

        if (size != 12) {
                warnx("failed, size %zu should be %u.  (26)",
                    size, 12);
                failures++;
        }

        free(buf);

        return (failures);
}