/*
 * SPDX-License-Identifier: GPL-2.0-or-later
 *
 * Bitmap.c unit-tests.
 *
 * Copyright (C) 2019, Red Hat, Inc.
 *
 * Author: Peter Xu <peterx@redhat.com>
 */

#include <stdlib.h>
#include "qemu/osdep.h"
#include "qemu/bitmap.h"

#define BMAP_SIZE  1024

static void check_bitmap_copy_with_offset(void)
{
    unsigned long *bmap1, *bmap2, *bmap3, total;

    bmap1 = bitmap_new(BMAP_SIZE);
    bmap2 = bitmap_new(BMAP_SIZE);
    bmap3 = bitmap_new(BMAP_SIZE);

    bmap1[0] = g_test_rand_int();
    bmap1[1] = g_test_rand_int();
    bmap1[2] = g_test_rand_int();
    bmap1[3] = g_test_rand_int();
    total = BITS_PER_LONG * 4;

    /* Shift 115 bits into bmap2 */
    bitmap_copy_with_dst_offset(bmap2, bmap1, 115, total);
    /* Shift another 85 bits into bmap3 */
    bitmap_copy_with_dst_offset(bmap3, bmap2, 85, total + 115);
    /* Shift back 200 bits back */
    bitmap_copy_with_src_offset(bmap2, bmap3, 200, total);

    g_assert_cmpmem(bmap1, total / BITS_PER_LONG,
                    bmap2, total / BITS_PER_LONG);

    bitmap_clear(bmap1, 0, BMAP_SIZE);
    /* Set bits in bmap1 are 100-245 */
    bitmap_set(bmap1, 100, 145);

    /* Set bits in bmap2 are 60-205 */
    bitmap_copy_with_src_offset(bmap2, bmap1, 40, 250);
    g_assert_cmpint(find_first_bit(bmap2, 60), ==, 60);
    g_assert_cmpint(find_next_zero_bit(bmap2, 205, 60), ==, 205);
    g_assert(test_bit(205, bmap2) == 0);

    /* Set bits in bmap3 are 135-280 */
    bitmap_copy_with_dst_offset(bmap3, bmap1, 35, 250);
    g_assert_cmpint(find_first_bit(bmap3, 135), ==, 135);
    g_assert_cmpint(find_next_zero_bit(bmap3, 280, 135), ==, 280);
    g_assert(test_bit(280, bmap3) == 0);

    g_free(bmap1);
    g_free(bmap2);
    g_free(bmap3);
}

typedef void (*bmap_set_func)(unsigned long *map, long i, long len);
static void bitmap_set_case(bmap_set_func set_func)
{
    unsigned long *bmap;
    int offset;

    bmap = bitmap_new(BMAP_SIZE);

    /* Set one bit at offset in second word */
    for (offset = 0; offset <= BITS_PER_LONG; offset++) {
        bitmap_clear(bmap, 0, BMAP_SIZE);
        set_func(bmap, BITS_PER_LONG + offset, 1);
        g_assert_cmpint(find_first_bit(bmap, 2 * BITS_PER_LONG),
                        ==, BITS_PER_LONG + offset);
        g_assert_cmpint(find_next_zero_bit(bmap,
                                           3 * BITS_PER_LONG,
                                           BITS_PER_LONG + offset),
                        ==, BITS_PER_LONG + offset + 1);
    }

    /* Both Aligned, set bits [BITS_PER_LONG, 3*BITS_PER_LONG] */
    set_func(bmap, BITS_PER_LONG, 2 * BITS_PER_LONG);
    g_assert_cmpuint(bmap[1], ==, -1ul);
    g_assert_cmpuint(bmap[2], ==, -1ul);
    g_assert_cmpint(find_first_bit(bmap, BITS_PER_LONG), ==, BITS_PER_LONG);
    g_assert_cmpint(find_next_zero_bit(bmap, 3 * BITS_PER_LONG, BITS_PER_LONG),
                    ==, 3 * BITS_PER_LONG);

    for (offset = 0; offset <= BITS_PER_LONG; offset++) {
        bitmap_clear(bmap, 0, BMAP_SIZE);
        /* End Aligned, set bits [BITS_PER_LONG - offset, 3*BITS_PER_LONG] */
        set_func(bmap, BITS_PER_LONG - offset, 2 * BITS_PER_LONG + offset);
        g_assert_cmpuint(bmap[1], ==, -1ul);
        g_assert_cmpuint(bmap[2], ==, -1ul);
        g_assert_cmpint(find_first_bit(bmap, BITS_PER_LONG),
                        ==, BITS_PER_LONG - offset);
        g_assert_cmpint(find_next_zero_bit(bmap,
                                           3 * BITS_PER_LONG,
                                           BITS_PER_LONG - offset),
                        ==, 3 * BITS_PER_LONG);
    }

    for (offset = 0; offset <= BITS_PER_LONG; offset++) {
        bitmap_clear(bmap, 0, BMAP_SIZE);
        /* Start Aligned, set bits [BITS_PER_LONG, 3*BITS_PER_LONG + offset] */
        set_func(bmap, BITS_PER_LONG, 2 * BITS_PER_LONG + offset);
        g_assert_cmpuint(bmap[1], ==, -1ul);
        g_assert_cmpuint(bmap[2], ==, -1ul);
        g_assert_cmpint(find_first_bit(bmap, BITS_PER_LONG),
                        ==, BITS_PER_LONG);
        g_assert_cmpint(find_next_zero_bit(bmap,
                                           3 * BITS_PER_LONG + offset,
                                           BITS_PER_LONG),
                        ==, 3 * BITS_PER_LONG + offset);
    }

    g_free(bmap);
}

static void check_bitmap_set(void)
{
    bitmap_set_case(bitmap_set);
    bitmap_set_case(bitmap_set_atomic);
}

int main(int argc, char **argv)
{
    g_test_init(&argc, &argv, NULL);

    g_test_add_func("/bitmap/bitmap_copy_with_offset",
                    check_bitmap_copy_with_offset);
    g_test_add_func("/bitmap/bitmap_set",
                    check_bitmap_set);

    g_test_run();

    return 0;
}
