/*
 * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.IdentityHashMap;
import java.util.Set;
import java.util.function.BiPredicate;
import java.util.stream.IntStream;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;

import static java.util.Map.entry;
import static org.testng.Assert.*;

/*
 * @test
 * @bug 8285295 8178355
 * @summary Basic tests for IdentityHashMap
 * @run testng Basic
 */

// NOTE: avoid using TestNG's assertEquals/assertNotEquals directly on two IDHM instances,
// as its logic for testing collections equality is suspect. Use checkEntries() to assert
// that a map's entrySet contains exactly the expected mappings. There are no guarantees about
// the identities of Map.Entry instances obtained from the entrySet; however, the keys and
// values they contain are guaranteed to have the right identity.

// TODO add tests using null keys and values
// TODO deeper testing of view collections including iterators, equals, contains, etc.
// TODO Map.Entry::setValue

public class Basic {
    /*
     * Helpers
     */

    record Box(int i) {
        Box(Box other) {
            this(other.i());
        }
    }

    // Checks that a collection contains exactly the given elements and no others, using the
    // provided predicate for equivalence. Checking is performed both using contains() on the
    // collection and by simple array searching. The latter is O(N^2) so is suitable only for
    // small arrays. No two of the given elements can be equivalent according to the predicate.

    // TODO: read out the elements using iterator and stream and check them too

    @SafeVarargs
    private <E> void checkContents(Collection<E> c, BiPredicate<E,E> p, E... given) {
        @SuppressWarnings("unchecked")
        E[] contents = (E[]) c.toArray();

        assertEquals(c.size(), given.length);
        assertEquals(contents.length, given.length);
        final int LEN = given.length;

        for (E e : given) {
            assertTrue(c.contains(e));
        }

        // Fill indexes array with position of a given element in the contents array,
        // or -1 if the given element cannot be found.

        int[] indexes = new int[LEN];

        outer:
        for (int i = 0; i < LEN; i++) {
            for (int j = 0; j < LEN; j++) {
                if (p.test(given[i], contents[j])) {
                    indexes[i] = j;
                    continue outer;
                }
            }
            indexes[i] = -1;
        }

        // If every given element matches a distinct element in the contents array,
        // the sorted indexes array will be the sequence [0..LEN-1].

        Arrays.sort(indexes);
        assertEquals(indexes, IntStream.range(0, LEN).toArray());
    }

    // Checks that the collection contains the given boxes, by identity.
    private void checkElements(Collection<Box> c, Box... given) {
        checkContents(c, (b1, b2) -> b1 == b2, given);
    }

    // Checks that the collection contains entries that have identical keys and values.
    // The entries themselves are not checked for identity.
    @SafeVarargs
    private void checkEntries(Collection<Map.Entry<Box, Box>> c, Map.Entry<Box, Box>... given) {
        checkContents(c, (e1, e2) -> e1.getKey() == e2.getKey() && e1.getValue() == e2.getValue(), given);
    }

    /*
     * Setup
     */

    final Box k1a = new Box(17);
    final Box k1b = new Box(17); // equals but != k1a
    final Box k2  = new Box(42);

    final Box v1a = new Box(30);
    final Box v1b = new Box(30); // equals but != v1a
    final Box v2  = new Box(99);

    IdentityHashMap<Box, Box> map;
    IdentityHashMap<Box, Box> map2;

    @BeforeMethod
    public void setup() {
        map = new IdentityHashMap<>();
        map.put(k1a, v1a);
        map.put(k1b, v1b);
        map.put(k2,  v2);

        map2 = new IdentityHashMap<>();
        map2.put(k1a, v1a);
        map2.put(k1b, v1b);
        map2.put(k2,  v2);
    }

    /*
     * Tests
     */

    // containsKey
    // containsValue
    // size
    @Test
    public void testSizeContainsKeyValue() {
        assertEquals(map.size(), 3);

        assertTrue(map.containsKey(k1a));
        assertTrue(map.containsKey(k1b));
        assertTrue(map.containsKey(k2));
        assertFalse(map.containsKey(new Box(k1a)));

        assertTrue(map.containsValue(v1a));
        assertTrue(map.containsValue(v1b));
        assertFalse(map.containsValue(new Box(v1a)));
        assertTrue(map.containsValue(v2));
    }

    // get
    @Test
    public void testGet() {
        assertSame(map.get(k1a), v1a);
        assertSame(map.get(k1b), v1b);
        assertSame(map.get(k2), v2);
        assertNull(map.get(new Box(k1a)));
    }

    // getOrDefault
    @Test
    public void testGetOrDefault() {
        Box other = new Box(22);

        assertSame(map.getOrDefault(k1a, other), v1a);
        assertSame(map.getOrDefault(k1b, other), v1b);
        assertSame(map.getOrDefault(new Box(k1a), other), other);
        assertSame(map.getOrDefault(k2, other), v2);
    }

    // clear
    // isEmpty
    @Test
    public void testClearEmpty() {
        assertFalse(map.isEmpty());
        map.clear();
        assertTrue(map.isEmpty());
    }

    // hashCode
    @Test
    public void testHashCode() {
        int expected = (System.identityHashCode(k1a) ^ System.identityHashCode(v1a)) +
                       (System.identityHashCode(k1b) ^ System.identityHashCode(v1b)) +
                       (System.identityHashCode(k2)  ^ System.identityHashCode(v2));
        assertEquals(map.hashCode(), expected);
        assertEquals(map.entrySet().hashCode(), expected);
    }

    // equals
    @Test
    public void testEquals() {
        assertTrue(map.equals(map));
        assertTrue(map.equals(map2));
        assertTrue(map2.equals(map));

        assertTrue(map.keySet().equals(map.keySet()));
        assertTrue(map.keySet().equals(map2.keySet()));
        assertTrue(map2.keySet().equals(map.keySet()));

        assertTrue(map.entrySet().equals(map.entrySet()));
        assertTrue(map.entrySet().equals(map2.entrySet()));
        assertTrue(map2.entrySet().equals(map.entrySet()));
    }

    // equals
    @Test
    public void testEqualsDifferentKey() {
        map2.remove(k1a);
        map2.put(new Box(k1a), v1a);

        assertFalse(map.equals(map2));
        assertFalse(map2.equals(map));

        assertFalse(map.keySet().equals(map2.keySet()));
        assertFalse(map2.keySet().equals(map.keySet()));

        assertFalse(map.entrySet().equals(map2.entrySet()));
        assertFalse(map2.entrySet().equals(map.entrySet()));
    }

    // equals
    @Test
    public void testEqualsDifferentValue() {
        map2.put(k1a, new Box(v1a));

        assertFalse(map.equals(map2));
        assertFalse(map2.equals(map));

        assertTrue(map.keySet().equals(map2.keySet()));
        assertTrue(map2.keySet().equals(map.keySet()));

        assertFalse(map.entrySet().equals(map2.entrySet()));
        assertFalse(map2.entrySet().equals(map.entrySet()));
    }

    // equals
    @Test
    public void testEqualsNewMapping() {
        map.put(new Box(k1a), new Box(v1a));

        assertFalse(map.equals(map2));
        assertFalse(map2.equals(map));

        assertFalse(map.keySet().equals(map2.keySet()));
        assertFalse(map2.keySet().equals(map.keySet()));

        assertFalse(map.entrySet().equals(map2.entrySet()));
        assertFalse(map2.entrySet().equals(map.entrySet()));
    }

    // equals
    @Test
    public void testEqualsMissingMapping() {
        var tmp = new IdentityHashMap<Box, Box>();
        tmp.put(k1a, v1a);
        tmp.put(k1b, v1b);

        assertFalse(map.equals(tmp));
        assertFalse(tmp.equals(map));

        assertFalse(map.keySet().equals(tmp.keySet()));
        assertFalse(tmp.keySet().equals(map.keySet()));

        assertFalse(map.entrySet().equals(tmp.entrySet()));
        assertFalse(tmp.entrySet().equals(map.entrySet()));
    }

    // keySet equals, contains
    @Test
    public void testKeySet() {
        Set<Box> keySet = map.keySet();

        checkElements(keySet, k1a, k1b, k2);
        assertFalse(keySet.contains(new Box(k1a)));
        assertTrue(map.keySet().equals(map2.keySet()));
        assertTrue(map2.keySet().equals(map.keySet()));
    }

    // keySet remove
    @Test
    public void testKeySetNoRemove() {
        Set<Box> keySet = map.keySet();
        boolean r = keySet.remove(new Box(k1a));

        assertFalse(r);
        checkElements(keySet, k1a, k1b, k2);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
        assertTrue(map.keySet().equals(map2.keySet()));
        assertTrue(map2.keySet().equals(map.keySet()));
    }

    // keySet remove
    @Test
    public void testKeySetRemove() {
        Set<Box> keySet = map.keySet();
        boolean r = keySet.remove(k1a);

        assertTrue(r);
        checkElements(keySet, k1b, k2);
        checkEntries(map.entrySet(), entry(k1b, v1b),
                                     entry(k2, v2));
        assertFalse(map.keySet().equals(map2.keySet()));
        assertFalse(map2.keySet().equals(map.keySet()));
    }

    // values
    @Test
    public void testValues() {
        Collection<Box> values = map.values();
        checkElements(values, v1a, v1b, v2);
        assertFalse(values.contains(new Box(v1a)));
    }

    // values remove
    @Test
    public void testValuesNoRemove() {
        Collection<Box> values = map.values();
        boolean r = values.remove(new Box(v1a));

        assertFalse(r);
        checkElements(values, v1a, v1b, v2);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // values remove
    @Test
    public void testValuesRemove() {
        Collection<Box> values = map.values();
        boolean r = values.remove(v1a);

        assertTrue(r);
        checkElements(values, v1b, v2);
        checkEntries(map.entrySet(), entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // entrySet equals, contains
    @Test
    public void testEntrySet() {
        Set<Map.Entry<Box,Box>> entrySet = map.entrySet();

        assertFalse(entrySet.contains(entry(new Box(k1a), v1a)));
        assertFalse(entrySet.contains(entry(k1b, new Box(v1b))));
        assertFalse(entrySet.contains(entry(new Box(k2), new Box(v2))));
        assertTrue(map.entrySet().equals(map2.entrySet()));
        checkEntries(entrySet, entry(k1a, v1a),
                               entry(k1b, v1b),
                               entry(k2, v2));
    }

    // entrySet remove
    @Test
    public void testEntrySetNoRemove() {
        Set<Map.Entry<Box, Box>> entrySet = map.entrySet();
        boolean r1 = entrySet.remove(entry(new Box(k1a), v1a));
        boolean r2 = entrySet.remove(entry(k1a, new Box(v1a)));

        assertFalse(r1);
        assertFalse(r2);
        assertTrue(entrySet.equals(map2.entrySet()));
        checkEntries(entrySet, entry(k1a, v1a),
                               entry(k1b, v1b),
                               entry(k2, v2));
    }

    // entrySet remove
    @Test
    public void testEntrySetRemove() {
        Set<Map.Entry<Box, Box>> entrySet = map.entrySet();
        boolean r = entrySet.remove(Map.entry(k1a, v1a));

        assertTrue(r);
        assertFalse(entrySet.equals(map2.entrySet()));
        assertFalse(map.entrySet().equals(map2.entrySet()));
        checkEntries(entrySet, entry(k1b, v1b),
                               entry(k2, v2));
        checkEntries(map.entrySet(), entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // put
    @Test
    public void testPutNew() {
        Box newKey = new Box(k1a);
        Box newVal = new Box(v1a);
        Box r = map.put(newKey, newVal);

        assertNull(r);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2),
                                     entry(newKey, newVal));
    }

    // put
    @Test
    public void testPutOverwrite() {
        Box newVal = new Box(v1a);
        Box r = map.put(k1a, newVal);

        assertSame(r, v1a);
        checkEntries(map.entrySet(), entry(k1a, newVal),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // putAll
    @Test
    public void testPutAll() {
        Box newKey  = new Box(k1a);
        Box newVal  = new Box(v1a);
        Box newValB = new Box(v1b);
        var argMap = new IdentityHashMap<Box, Box>();
        argMap.put(newKey, newVal); // new entry
        argMap.put(k1b, newValB);   // will overwrite value
        map.putAll(argMap);

        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, newValB),
                                     entry(k2, v2),
                                     entry(newKey, newVal));
    }

    // putIfAbsent
    @Test
    public void testPutIfAbsentNoop() {
        Box r = map.putIfAbsent(k1a, new Box(v1a)); // no-op

        assertSame(r, v1a);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // putIfAbsent
    @Test
    public void testPutIfAbsentAddsNew() {
        Box newKey = new Box(k1a);
        Box newVal = new Box(v1a);
        Box r = map.putIfAbsent(newKey, newVal); // adds new entry

        assertNull(r);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2),
                                     entry(newKey, newVal));
    }

    // remove(Object)
    @Test
    public void testRemoveKey() {
        Box r = map.remove(k1b);

        assertSame(r, v1b);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k2, v2));
    }

    // remove(Object, Object) absent key, absent value
    @Test
    public void testRemoveAA() {
        Box k1c = new Box(k1a);
        Box v1c = new Box(v1a);
        assertFalse(map.remove(k1c, v1c));
        checkEntries(map.entrySet(),
                entry(k1a, v1a),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // remove(Object, Object) absent key, present value
    @Test
    public void testRemoveAV() {
        Box k1c = new Box(k1a);
        assertFalse(map.remove(k1c, v1a));
        checkEntries(map.entrySet(),
                     entry(k1a, v1a),
                     entry(k1b, v1b),
                     entry(k2, v2));
    }

    // remove(Object, Object) present key, absent value
    @Test
    public void testRemoveKA() {
        Box v1c = new Box(v1a);
        assertFalse(map.remove(k1a, v1c));
        checkEntries(map.entrySet(),
                entry(k1a, v1a),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // remove(Object, Object) present key, present value
    @Test
    public void testRemoveKV() {
        assertTrue(map.remove(k1a, v1a));
        checkEntries(map.entrySet(),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // replace(K, V, V) absent key, absent oldValue
    @Test
    public void testReplaceAA() {
        Box k1c = new Box(k1a);
        Box v1c = new Box(v1a);
        Box newVal = new Box(v2);
        assertFalse(map.replace(k1c, v1c, newVal));
        checkEntries(map.entrySet(),
                entry(k1a, v1a),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // replace(K, V, V) absent key, present oldValue
    @Test
    public void testReplaceAV() {
        Box k1c = new Box(k1a);
        Box newVal = new Box(v2);
        assertFalse(map.replace(k1c, v1a, newVal));
        checkEntries(map.entrySet(),
                entry(k1a, v1a),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // replace(K, V, V) present key, absent oldValue
    @Test
    public void testReplaceKA() {
        Box v1c = new Box(v1a);
        Box newVal = new Box(v2);
        assertFalse(map.replace(k1a, v1c, newVal));
        checkEntries(map.entrySet(),
                entry(k1a, v1a),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // replace(K, V, V) present key, present oldValue
    @Test
    public void testReplaceKV() {
        Box newVal = new Box(v2);
        assertTrue(map.replace(k1a, v1a, newVal));
        checkEntries(map.entrySet(),
                entry(k1a, newVal),
                entry(k1b, v1b),
                entry(k2, v2));
    }

    // AN: key absent, remappingFunction returns null
    @Test
    public void testComputeAN() {
        Box newKey = new Box(k1a);
        Box r = map.compute(newKey, (k, v) -> null);

        assertNull(r);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // AV: key absent, remappingFunction returns non-null value
    @Test
    public void testComputeAV() {
        Box newKey = new Box(k1a);
        Box newVal = new Box(v1a);
        Box r = map.compute(newKey, (k, v) -> newVal);

        assertSame(r, newVal);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2),
                                     entry(newKey, newVal));
    }

    // PN: key present, remappingFunction returns null
    @Test
    public void testComputePN() {
        Box r = map.compute(k1a, (k, v) -> null);

        assertNull(r);
        checkEntries(map.entrySet(), entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // PV: key present, remappingFunction returns non-null value
    @Test
    public void testComputePV() {
        Box newVal = new Box(v1a);
        Box r = map.compute(k1a, (k, v) -> newVal);

        assertSame(r, newVal);
        checkEntries(map.entrySet(), entry(k1a, newVal),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // computeIfAbsent
    @Test
    public void testComputeIfAbsentIsCalled() {
        boolean[] called = new boolean[1];
        Box newKey = new Box(k1a);
        Box newVal = new Box(v1a);
        Box r = map.computeIfAbsent(newKey, k -> { called[0] = true; return newVal; });

        assertSame(r, newVal);
        assertTrue(called[0]);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2),
                                     entry(newKey, newVal));
    }

    // computeIfAbsent
    @Test
    public void testComputeIfAbsentNotCalled() {
        boolean[] called = new boolean[1];
        Box r = map.computeIfAbsent(k1a, k -> { called[0] = true; return null; });

        assertSame(r, v1a);
        assertFalse(called[0]);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // computeIfAbsent
    @Test
    public void testComputeIfAbsentNullReturn() {
        boolean[] called = new boolean[1];
        Box newKey = new Box(k1a);
        Box r = map.computeIfAbsent(newKey, k -> { called[0] = true; return null; });

        assertNull(r);
        assertTrue(called[0]);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // computeIfPresent
    @Test
    public void testComputeIfPresentIsCalled() {
        boolean[] called = new boolean[1];
        Box newVal = new Box(v1a);
        Box r = map.computeIfPresent(k1a, (k, v) -> { called[0] = true; return newVal; });

        assertSame(r, newVal);
        assertTrue(called[0]);
        checkEntries(map.entrySet(), entry(k1a, newVal),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // computeIfPresent
    @Test
    public void testComputeIfPresentNotCalled() {
        boolean[] called = new boolean[1];
        Box r = map.computeIfPresent(new Box(k1a), (k, v) -> { called[0] = true; return null; });

        assertNull(r);
        assertFalse(called[0]);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // computeIfPresent
    @Test
    public void testComputeIfPresentNullReturn() {
        boolean[] called = new boolean[1];
        Box r = map.computeIfPresent(k1a, (k, v) -> { called[0] = true; return null; });

        assertNull(r);
        assertTrue(called[0]);
        checkEntries(map.entrySet(), entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // merge
    @Test
    public void testMergeAbsent() {
        boolean[] called = new boolean[1];
        Box newKey = new Box(k1a);
        Box newVal = new Box(v1a);
        Box r = map.merge(newKey, newVal, (v1, v2) -> { called[0] = true; return newVal; });

        assertSame(r, newVal);
        assertFalse(called[0]);
        checkEntries(map.entrySet(), entry(k1a, v1a),
                                     entry(k1b, v1b),
                                     entry(k2, v2),
                                     entry(newKey, newVal));
    }

    // merge
    @Test
    public void testMergePresent() {
        boolean[] called = new boolean[1];
        Box val2 = new Box(47);
        Box[] mergedVal = new Box[1];
        Box r = map.merge(k1a, val2, (v1, v2) -> {
            called[0] = true;
            mergedVal[0] = new Box(v1.i + v2.i);
            return mergedVal[0];
        });

        assertSame(r, mergedVal[0]);
        assertTrue(called[0]);
        checkEntries(map.entrySet(), entry(k1a, mergedVal[0]),
                                     entry(k1b, v1b),
                                     entry(k2, v2));
    }

    // forEach
    @Test
    public void testForEach() {
        @SuppressWarnings("unchecked")
        List<Map.Entry<Box, Box>> entries = new ArrayList<>();
        map.forEach((k, v) -> entries.add(entry(k, v)));
        checkEntries(entries, entry(k1a, v1a),
                              entry(k1b, v1b),
                              entry(k2, v2));
    }

    // replaceAll
    @Test
    public void testReplaceAll() {
        List<Map.Entry<Box, Box>> replacements = new ArrayList<>();

        map.replaceAll((k, v) -> {
            Box v1 = new Box(v);
            replacements.add(entry(k, v1));
            return v1;
        });

        @SuppressWarnings("unchecked")
        var replacementArray = (Map.Entry<Box, Box>[]) replacements.toArray(Map.Entry[]::new);
        checkEntries(map.entrySet(), replacementArray);
    }
}
