/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.tests.junit.transparentindirection;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.Vector;

import org.eclipse.persistence.descriptors.changetracking.CollectionChangeEvent;
import org.eclipse.persistence.descriptors.changetracking.MapChangeEvent;
import org.eclipse.persistence.indirection.IndirectCollectionsFactory;
import org.eclipse.persistence.indirection.IndirectMap;
import org.eclipse.persistence.indirection.ValueHolderInterface;
import org.eclipse.persistence.internal.indirection.QueryBasedValueHolder;
import org.eclipse.persistence.queries.ReadAllQuery;
import org.eclipse.persistence.sessions.DatabaseRecord;
import org.eclipse.persistence.testing.tests.transparentindirection.ZTestCase;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

/**
 * Test a simple IndirectMap.
 * @author: Big Country
 */
@RunWith(Parameterized.class)
public class IndirectMapTest {

    public static final class M<K, V> extends IndirectMap<K, V> {}

    private Hashtable<String, String> map;
    private IndirectMap<String, String> testMap;
    private Listener testMapLsn;
    private Class<? extends IndirectMap> cls;
    private boolean useListener;

    @Parameters(name = "{0}, {1}")
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
                 { IndirectMap.class, true }, { IndirectMap.class, false }, { M.class, true }, { M.class, false }
           });
    }

    public IndirectMapTest(Class<? extends IndirectMap> cls, boolean useListener) {
        this.cls = cls;
        this.useListener = useListener;
    }

    /**
     * Assert that the elements in two dictionaries are equal. If they are not,
     * throw an AssertionFailedError. Order of the elements is significant.
     * @param message the error message
     * @param expected the expected value of a Map
     * @param actual the actual value of a Map
     */
    protected void assertElementsEqual(String message, Map expected, Map actual) {
        if (expected == actual) {
            return;
        }
        if (expected.size() != actual.size()) {
            assertTrue(ZTestCase.notEqualsMessage(message, expected, actual), false);
        }
        for (Iterator stream = expected.keySet().iterator(); stream.hasNext();) {
            Object key = stream.next();
            if (!expected.get(key).equals(actual.get(key))) {
                assertTrue(ZTestCase.notEqualsMessage(message, expected, actual), false);
            }
        }
    }

    /**
     * Assert that the elements in two dictionaries are equal. If they are not,
     * throw an AssertionFailedError.
     * @param expected the expected value of a Map
     * @param actual the actual value of a Map
     */
    protected void assertElementsEqual(Map expected, Map actual) {
        assertElementsEqual("", expected, actual);
    }

    /**
     * set up the test fixture:
     * 1. an IndirectMap based on a Hashtable
     */
    @Before
    public void setUp() {
        map = this.setUpMap();
        Object temp = new Hashtable(map);

        ValueHolderInterface vh = new QueryBasedValueHolder(new ReadAllQuery(), new DatabaseRecord(), new TestSession(temp));
        if (cls == null) {
            testMap = IndirectCollectionsFactory.createIndirectMap();
        } else {
            try {
                testMap = cls.getConstructor().newInstance();
            } catch (ReflectiveOperationException e) {
                throw new RuntimeException(e);
            }
        }
        testMap.setValueHolder(vh);
        if (useListener) {
            testMapLsn = new Listener();
            testMap._persistence_setPropertyChangeListener(testMapLsn);
        }
    }

    protected Hashtable<String, String> setUpMap() {
        Hashtable<String, String> result = new Hashtable<>();
        result.put("zero", "000");
        result.put("one", "111");
        result.put("two", "222");
        result.put("three", "333");
        result.put("four", "444");
        result.put("five", "555");
        result.put("six", "666");
        result.put("seven", "777");
        result.put("eight", "888");
        result.put("nine", "999");
        return result;
    }

    /**
     * nothing for now...
     */
    @After
    public void tearDown() {
        if (useListener) {
            testMapLsn.events.clear();
        }
    }

    @Test
    public void testClear() {
        int originalSize = testMap.size();
        map.clear();
        testMap.clear();

        assertEquals(map, testMap);
        assertTrue(testMap.isEmpty());
        assertRemoveEvents(originalSize);
    }

    @Test
    public void testContains() {
        assertTrue(testMap.contains(map.elements().nextElement()));
        assertNoEvents();
    }

    @Test
    public void testContainsKey() {
        assertTrue(testMap.containsKey(map.keys().nextElement()));
        assertNoEvents();
    }

    @Test
    public void testContainsValue() {
        assertTrue(testMap.containsValue(map.elements().nextElement()));
        assertNoEvents();
    }

    @Test
    public void testElements() {
        assertTrue("Map Does not contain elements from test", map.contains(testMap.elements().nextElement()));
        assertNoEvents();
    }

    @Test
    public void testEntrySet() {
        assertEquals(map.entrySet(), testMap.entrySet());
        assertNoEvents();
    }

    @Test
    public void testEntrySetAdd() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        UnsupportedOperationException uoe = null;
        try {
            entrySet.add(new MapEntry("sampleKey", "sampleValue"));
        } catch (UnsupportedOperationException ex) {
            uoe = ex;
        }
        assertNotNull(uoe);
        try {
            testEntrySet.add(new MapEntry("sampleKey", "sampleValue"));
            fail("should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException ex) {
            assertEquals(uoe.getClass(), ex.getClass());
            assertEquals(uoe.getMessage(), ex.getMessage());
        }
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testEntrySetAddAll() {
        Collection<Map.Entry<String, String>> collection = new HashSet<>();
        collection.add(new MapEntry("sampleKey1", "sampleValue1"));
        collection.add(new MapEntry("sampleKey2", "sampleValue2"));
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        UnsupportedOperationException uoe = null;
        try {
            entrySet.addAll(collection);
        } catch (UnsupportedOperationException ex) {
            uoe = ex;
        }
        assertNotNull(uoe);
        try {
            testEntrySet.addAll(collection);
            fail("should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException ex) {
            assertEquals(uoe.getClass(), ex.getClass());
            assertEquals(uoe.getMessage(), ex.getMessage());
        }
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testEntrySetClear() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        entrySet.clear();
        testEntrySet.clear();
        assertEquals(map, testMap);
        assertNull(testMap.get("one"));
        assertRemoveEvents(10);
    }

    @Test
    public void testEntrySetSize() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        assertEquals(map, testMap);
        assertEquals(entrySet.size(), testEntrySet.size());
        assertNoEvents();
    }

    @Test
    public void testEntrySetRemove() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        Map.Entry<String, String> toRemove = null;
        Iterator<Entry<String, String>> iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Entry<String, String> next = iterator.next();
            if ("one".equals(next.getKey())) {
                toRemove = next;
                break;
            }
        }
        boolean result1 = entrySet.remove(toRemove);
        boolean result2 = testEntrySet.remove(toRemove);
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(1);
    }

    @Test
    public void testEntrySetRemoveAll() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        Collection<Map.Entry<String, String>> toRemove = new HashSet<>();
        Iterator<Entry<String, String>> iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Entry<String, String> next = iterator.next();
            if ("one".equals(next.getKey()) || "two".equals(next.getKey())) {
                toRemove.add(next);
            }
            if (toRemove.size() == 2) {
                break;
            }
        }
        boolean result1 = entrySet.removeAll(toRemove);
        boolean result2 = testEntrySet.removeAll(toRemove);
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(2);
    }

    @Test
    public void testEntrySetRemoveIf() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        boolean result1 = entrySet.removeIf(entry -> "one".equals(entry.getKey()));
        boolean result2 = testEntrySet.removeIf(entry -> "one".equals(entry.getKey()));
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(1);
    }

    @Test
    public void testEntrySetRetainAll() {
        Set<Map.Entry<String, String>> entrySet = map.entrySet();
        Set<Map.Entry<String, String>> testEntrySet = testMap.entrySet();
        Collection<Map.Entry<String, String>> toRetain = new HashSet<>();
        Iterator<Entry<String, String>> iterator = entrySet.iterator();
        while (iterator.hasNext()) {
            Entry<String, String> next = iterator.next();
            if ("one".equals(next.getKey()) || "two".equals(next.getKey())) {
                toRetain.add(next);
            }
            if (toRetain.size() == 2) {
                break;
            }
        }
        boolean result1 = entrySet.retainAll(toRetain);
        boolean result2 = testEntrySet.retainAll(toRetain);
        assertEquals(map, testMap);
        assertNotNull(testMap.get("one"));
        assertEquals(result1, result2);
        assertNull(testMap.get("six"));
        assertRemoveEvents(8);
    }

    @Test
    public void testEquals() {
        assertFalse(testMap == map);
        assertTrue(testMap.equals(map));
        assertNoEvents();
    }

    @Test
    public void testGet() {
        assertEquals(map.get("six"), testMap.get("six"));
        assertNoEvents();
    }

    @Test
    public void testHashCode() {
        assertEquals(map.hashCode(), testMap.hashCode());
        assertNoEvents();
    }

    @Test
    public void testIsEmpty() {
        assertTrue(!testMap.isEmpty());
        assertNoEvents();
    }

    @Test
    public void testKeys() {
        assertFalse("Map Does not contain keys from test", map.contains(testMap.keys().nextElement()));
        assertNoEvents();
    }

    @Test
    public void testKeySet() {
        assertEquals(map.entrySet(), testMap.entrySet());
        assertNoEvents();
    }

    @Test
    public void testKeySetAdd() {
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        UnsupportedOperationException uoe = null;
        try {
            keySet.add("newKey");
        } catch (UnsupportedOperationException ex) {
            uoe = ex;
        }
        assertNotNull(uoe);
        try {
            testKeySet.add("newKey");
            fail("should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException ex) {
            assertEquals(uoe.getClass(), ex.getClass());
            assertEquals(uoe.getMessage(), ex.getMessage());
        }
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testKeySetAddAll() {
        Collection<String> collection = new HashSet<>();
        collection.add("sampleKey1");
        collection.add("sampleKey2");
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        UnsupportedOperationException uoe = null;
        try {
            keySet.addAll(collection);
        } catch (UnsupportedOperationException ex) {
            uoe = ex;
        }
        assertNotNull(uoe);
        try {
            testKeySet.addAll(collection);
            fail("should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException ex) {
            assertEquals(uoe.getClass(), ex.getClass());
            assertEquals(uoe.getMessage(), ex.getMessage());
        }
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testKeySetClear() {
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        keySet.clear();
        testKeySet.clear();
        assertEquals(map, testMap);
        assertNull(testMap.get("one"));
        assertRemoveEvents(10);
    }

    @Test
    public void testKeySetSize() {
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        assertEquals(map, testMap);
        assertEquals(keySet.size(), testKeySet.size());
        assertNoEvents();
    }

    @Test
    public void testKeySetRemove() {
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        boolean result1 = keySet.remove("one");
        boolean result2 = testKeySet.remove("one");
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(1);
    }

    @Test
    public void testKeySetRemoveAll() {
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        Collection<String> toRemove = new HashSet<>();
        toRemove.add("one");
        toRemove.add("two");
        boolean result1 = keySet.removeAll(toRemove);
        boolean result2 = testKeySet.removeAll(toRemove);
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(2);
    }

    @Test
    public void testKeySetRemoveIf() {
        // remove 2 items - 'six' and 'seven'
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        boolean result1 = keySet.removeIf(key -> key.startsWith("s"));
        boolean result2 = testKeySet.removeIf(key -> key.startsWith("s"));
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("six"));
        assertRemoveEvents(2);
    }

    @Test
    public void testKeySetRetainAll() {
        Set<String> keySet = map.keySet();
        Set<String> testKeySet = testMap.keySet();
        Collection<String> toRetain = new HashSet<>();
        toRetain.add("one");
        toRetain.add("two");
        boolean result1 = keySet.retainAll(toRetain);
        boolean result2 = testKeySet.retainAll(toRetain);
        assertEquals(map, testMap);
        assertNotNull(testMap.get("one"));
        assertEquals(result1, result2);
        assertNull(testMap.get("six"));
        assertRemoveEvents(8);
    }

    @Test
    public void testPut() {
        String key = "foo";
        String value = "bar";
        String result1 = map.put(key, value);
        String result2 = testMap.put(key, value);

        assertEquals(map, testMap);
        assertTrue(testMap.containsKey(key));
        assertTrue(testMap.contains(value));
        assertEquals(result1, result2);
        assertAddEvents(1);
    }

    @Test
    public void testPutAll() {
        Hashtable<String, String> temp = new Hashtable<>();
        temp.put("foo", "bar");
        temp.put("sna", "fu");

        map.putAll(temp);
        testMap.putAll(temp);
        assertEquals(map, testMap);
        for (Enumeration stream = temp.keys(); stream.hasMoreElements();) {
            assertTrue(testMap.containsKey(stream.nextElement()));
        }
        for (Enumeration stream = temp.elements(); stream.hasMoreElements();) {
            assertTrue(testMap.contains(stream.nextElement()));
        }
        assertAddEvents(2);
    }

    @Test
    public void testRemove() {
        String temp = "one";
        String result1 = map.remove(temp);
        String result2 = testMap.remove(temp);
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNotNull(result2);
        assertTrue(!testMap.containsKey(temp));
        assertRemoveEvents(1);
    }

    @Test
    public void testSize() {
        assertEquals(map.size(), testMap.size());
        assertNoEvents();
    }

    @Test
    public void testValues() {
        assertEquals(map.size(), testMap.values().size());

        for (Iterator stream = testMap.values().iterator(); stream.hasNext();) {
            assertTrue(map.contains(stream.next()));
        }
        map.values().removeAll(testMap.values());
        assertTrue(map.values().isEmpty());
        assertNoEvents();
    }

    @Test
    public void testValuesAdd() {
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        UnsupportedOperationException uoe = null;
        try {
            keySet.add("newValue");
        } catch (UnsupportedOperationException ex) {
            uoe = ex;
        }
        assertNotNull(uoe);
        try {
            testKeySet.add("newValue");
            fail("should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException ex) {
            assertEquals(uoe.getClass(), ex.getClass());
            assertEquals(uoe.getMessage(), ex.getMessage());
        }
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testValuesAddAll() {
        Collection<String> collection = new HashSet<>();
        collection.add("newValue1");
        collection.add("newValue2");
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        UnsupportedOperationException uoe = null;
        try {
            keySet.addAll(collection);
        } catch (UnsupportedOperationException ex) {
            uoe = ex;
        }
        assertNotNull(uoe);
        try {
            testKeySet.addAll(collection);
            fail("should throw UnsupportedOperationException");
        } catch (UnsupportedOperationException ex) {
            assertEquals(uoe.getClass(), ex.getClass());
            assertEquals(uoe.getMessage(), ex.getMessage());
        }
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testValuesClear() {
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        keySet.clear();
        testKeySet.clear();
        assertEquals(map, testMap);
        assertNull(testMap.get("one"));
        assertRemoveEvents(10);
    }

    @Test
    public void testValuesSize() {
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        assertEquals(map, testMap);
        assertEquals(keySet.size(), testKeySet.size());
        assertNoEvents();
    }

    @Test
    public void testValuesRemove() {
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        boolean result1 = keySet.remove("111");
        boolean result2 = testKeySet.remove("111");
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(1);
    }

    @Test
    public void testValuesRemoveAll() {
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        Collection<String> toRemove = new HashSet<>();
        toRemove.add("111");
        toRemove.add("222");
        boolean result1 = keySet.removeAll(toRemove);
        boolean result2 = testKeySet.removeAll(toRemove);
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("one"));
        assertRemoveEvents(2);
    }

    @Test
    public void testValuesRemoveIf() {
        // remove 2 items - 'six' and 'seven'
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        boolean result1 = keySet.removeIf(key -> key.startsWith("2"));
        boolean result2 = testKeySet.removeIf(key -> key.startsWith("2"));
        assertEquals(map, testMap);
        assertEquals(result1, result2);
        assertNull(testMap.get("two"));
        assertRemoveEvents(1);
    }


    @Test
    public void testValueRetainAll() {
        Collection<String> keySet = map.values();
        Collection<String> testKeySet = testMap.values();
        Collection<String> toRetain = new HashSet<>();
        toRetain.add("111");
        toRetain.add("222");
        boolean result1 = keySet.retainAll(toRetain);
        boolean result2 = testKeySet.retainAll(toRetain);
        assertEquals(map, testMap);
        assertNotNull(testMap.get("one"));
        assertEquals(result1, result2);
        assertNull(testMap.get("six"));
        assertRemoveEvents(8);
    }

    //Java SE 8 API
    @Test
    public void testReplace() {
        assertEquals(map, testMap);
        Object o = testMap.replace("one", "1");
        assertEquals(map.replace("one", "1"), o);
        assertNotNull("Should return value", o);
        assertEquals("111", o);
        assertEquals("1", testMap.get("one"));
        assertEquals(map, testMap);
        assertRemoveAddEvents(1);

        assertNull(map.replace("blablablabla", "whatever"));
        assertNull(testMap.replace("blablablabla", "whatever"));
        assertEquals(map, testMap);
        assertRemoveAddEvents(1);
    }

    @Test
    public void testReplaceWithDefault() {
        assertEquals("111", testMap.get("one"));
        Object o = testMap.replace("one", "1", "1234");
        assertEquals(map.replace("one", "1", "1234"), o);
        assertFalse("Should return false", (boolean) o);
        assertFalse("Should not have '1234'", testMap.containsValue("1234"));
        assertEquals(map, testMap);
        assertNoEvents();

        assertEquals("111", testMap.get("one"));
        o = testMap.replace("one", "111", "1234");
        assertEquals(map.replace("one", "111", "1234"), o);
        assertTrue("Should return true", (boolean) o);
        assertEquals("1234", testMap.get("one"));
        assertEquals(map, testMap);
        assertRemoveAddEvents(1);
    }

    @Test
    public void testGetOrDefault() {
        assertFalse(testMap.containsKey("temp"));
        Object o = testMap.getOrDefault("temp", "1234");
        assertNotNull("Should return value", o);
        assertEquals("1234", o);

        assertTrue(testMap.containsKey("one"));
        o = testMap.getOrDefault("one", "5678");
        assertNotNull("Should return value", o);
        assertEquals("111", o);
        assertNoEvents();
    }

    @Test
    public void testPutIfAbsent() {
        assertFalse(testMap.containsKey("temp"));
        Object o = testMap.putIfAbsent("temp", "1234");
        assertNull("Should return null", o);
        assertAddEvents(1);

        assertTrue(testMap.containsKey("temp"));
        o = testMap.putIfAbsent("temp", "5678");
        assertNotNull("Should return value", o);
        assertEquals("1234", o);
        assertAddEvents(1);
    }

    @Test
    public void testRemoveTwoArgs() {
        assertEquals("111", testMap.get("one"));
        Object o = testMap.remove("one", "1234");
        assertFalse("Should return false", (boolean) o);
        assertNoEvents();

        assertEquals("111", testMap.get("one"));
        o = testMap.remove("one", "111");
        assertTrue("Should return true", (boolean) o);
        assertNull(testMap.get("one"));
        assertRemoveEvents(1);
    }

    @Test
    public void testForEach() {
        final Vector<String> v1 = new Vector<>();
        final Vector<String> v2 = new Vector<>();
        map.forEach((k, v) -> {v1.add(k);v1.add(v);});
        testMap.forEach((k, v) -> {v2.add(k);v2.add(v);});
        ZTestCase.assertUnorderedElementsEqual(v1, v2);
        assertEquals(map, testMap);
        assertNoEvents();
    }

    @Test
    public void testReplaceAll() {
        assertEquals(map, testMap);
        map.replaceAll((k,v) -> v += "sufix");
        testMap.replaceAll((k,v) -> v += "sufix");
        assertEquals(map, testMap);
        assertRemoveAddEvents(testMap.size());
    }

    @Test
    public void testCompute() {
        assertEquals(map, testMap);
        String s1 = map.compute("one", (k,v) -> v += "suffix");
        String s2 = testMap.compute("one", (k,v) -> v += "suffix");
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertEquals("111suffix", testMap.get("one"));
        assertRemoveAddEvents(1);
    }

    @Test
    public void testCompute2() {
        assertEquals(map, testMap);
        String s1 = map.compute("notExist", (k,v) -> v += "suffix");
        String s2 = testMap.compute("notExist", (k,v) -> v += "suffix");
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertEquals("nullsuffix", testMap.get("notExist"));
        assertAddEvents(1);
    }

    @Test
    public void testComputeIfPresent() {
        assertEquals(map, testMap);
        String s1 = map.computeIfPresent("one", (k,v) -> v += "suffix");
        String s2 = testMap.computeIfPresent("one", (k,v) -> v += "suffix");
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertEquals("111suffix", testMap.get("one"));
        assertRemoveAddEvents(1);
    }

    @Test
    public void testComputeIfPresent2() {
        assertEquals(map, testMap);
        String s1 = map.computeIfPresent("notExist", (k,v) -> v += "suffix");
        String s2 = testMap.computeIfPresent("notExist", (k,v) -> v += "suffix");
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertNull(testMap.get("notExist"));
        assertNoEvents();;
    }

    @Test
    public void testComputeIfAbsent() {
        assertEquals(map, testMap);
        String s1 = map.computeIfAbsent("one", k -> "newitem");
        String s2 = testMap.computeIfAbsent("one", k -> "newitem");
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertEquals("111", testMap.get("one"));
        assertNoEvents();
    }

    @Test
    public void testComputeIfAbsent2() {
        assertEquals(map, testMap);
        String s1 = map.computeIfAbsent("notExist", k -> "newitem");
        String s2 = testMap.computeIfAbsent("notExist", k -> "newitem");
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertAddEvents(1);
    }

    @Test
    public void testMerge() {
        assertEquals(map, testMap);
        String s1 = map.merge("one", "custom", String::concat);
        String s2 = testMap.merge("one", "custom", String::concat);
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertEquals("111custom", testMap.get("one"));
        assertRemoveAddEvents(1);
    }

    @Test
    public void testMerge2() {
        assertEquals(map, testMap);
        String s1 = map.merge("notExist", "custom", String::concat);
        String s2 = testMap.merge("notExist", "custom", String::concat);
        assertEquals(s1, s2);
        assertEquals(map, testMap);
        assertEquals("111", testMap.get("one"));
        assertAddEvents(1);
    }

    private void assertNoEvents() {
        if (useListener) {
            assertTrue(testMapLsn.events.isEmpty());
        }
    }

    private void assertAddEvents(int count) {
        if (useListener) {
            assertEquals("events do not match", count, testMapLsn.events.size());
            for (MapChangeEvent cce : testMapLsn.events) {
                assertEquals("expected add event", CollectionChangeEvent.ADD, cce.getChangeType());
            }
        }
    }

    private void assertRemoveEvents(int count) {
        if (useListener) {
            assertEquals("events do not match", count, testMapLsn.events.size());
            for (MapChangeEvent cce : testMapLsn.events) {
                assertEquals("expected add event", CollectionChangeEvent.REMOVE, cce.getChangeType());
            }
        }
    }

    private void assertRemoveAddEvents(int count) {
        if (useListener) {
            int totalEvents = count * 2;
            assertEquals("events do not match", totalEvents, testMapLsn.events.size());
            for (int i = 0; i < totalEvents;) {
                MapChangeEvent removeEvent = testMapLsn.events.get(i++);
                MapChangeEvent addEvent = testMapLsn.events.get(i++);
                assertEquals("expected remove event", CollectionChangeEvent.REMOVE, removeEvent.getChangeType());
                assertEquals("expected add event", CollectionChangeEvent.ADD, addEvent.getChangeType());
                assertFalse("removed: '" + removeEvent.getNewValue() + "', new: '" + addEvent.getNewValue() + "'",
                        removeEvent.getNewValue().equals(addEvent.getNewValue()));
            }
        }
    }

    private static final class Listener implements PropertyChangeListener {
        private List<MapChangeEvent> events = new ArrayList<>();

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            events.add((MapChangeEvent)evt);
        }

    }

    private static final class MapEntry<K, V> implements Map.Entry<K, V> {

        private K key;
        private V value;

        public MapEntry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) {
            this.value = value;
            return this.value;
        }

    }
}
