/*
 * 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.identitymaps;

import java.util.Iterator;
import java.util.Map;
import java.util.Vector;

import org.eclipse.persistence.internal.identitymaps.CacheKey;
import org.eclipse.persistence.internal.identitymaps.WeakIdentityMap;
import org.eclipse.persistence.queries.InsertObjectQuery;
import org.eclipse.persistence.testing.models.employee.domain.Employee;
import org.eclipse.persistence.testing.framework.*;

//bug4649617  Test if there is any memory leak in InsertObjectQuery with WeakIdentityMap.
public class InsertWeakIdentityMapTest extends TestCase {
    protected Class originalIdentityMapClass;
    protected int originalIdentityMapSize;
    protected int identityMapSize = 10;

    public InsertWeakIdentityMapTest() {
        setDescription("Test if there is any memory leak in InsertObjectQuery with WeakIdentityMap.");
    }

    protected WeakIdentityMap getIdentityMap() {
        return (WeakIdentityMap)getAbstractSession().getIdentityMapAccessorInstance().getIdentityMap(Employee.class);
    }

    @Override
    public void reset() {
        getSession().getDescriptor(Employee.class).setIdentityMapClass(originalIdentityMapClass);
        getSession().getDescriptor(Employee.class).setIdentityMapSize(originalIdentityMapSize);
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
    }

    @Override
    public void setup() {
        originalIdentityMapClass = getSession().getDescriptor(Employee.class).getIdentityMapClass();
        originalIdentityMapSize = getSession().getDescriptor(Employee.class).getIdentityMapSize();
        getSession().getDescriptor(Employee.class).setIdentityMapClass(WeakIdentityMap.class);
        getSession().getDescriptor(Employee.class).setIdentityMapSize(identityMapSize);
        getSession().getIdentityMapAccessor().initializeIdentityMaps();
    }

    @Override
    public void test() {
        for (int index = 0; index < (identityMapSize * 2); index++) {
            Employee obj = new Employee();
            InsertObjectQuery query = new InsertObjectQuery(obj);
            getAbstractSession().beginTransaction();
            getSession().executeQuery(query);
            getAbstractSession().rollbackTransaction();
            System.gc();
        }
        System.gc();
    }

    @Override
    public void verify() {
        // Force full GC.
        for (int loops = 0; loops < 10; loops++) {
            // The jdk1.2.0 on the Testing machine treats the weak reference as a softweak reference so we must waste memory
            Vector vector = new Vector(50000);
            for (int i = 0; i < 50000; i++) {
                vector.add(new java.math.BigDecimal(i));
            }

            // Force garbage collection, which should clear the cache.
            System.gc();
            System.runFinalization();
        }
        // Check to see if maximum size was maintained.  The maximum size is identityMapSize + 2, because System.gc()
        //inside the for block does not garbage collect the object just inserted, also in put(CacheKey) method of WeakIdentityMap
        //it checks if (getCleanupCount() > getMaxSize()) instead of =, which adds one more.
        int maxSize = identityMapSize + 2;
        if (getIdentityMap().getSize() > maxSize) {
            throw new TestErrorException("Weak identity map " + getIdentityMap() + " contains " +
                                         getIdentityMap().getSize() + " objects.  " +
                                         "The specified maximum size for this cache was " + maxSize + ".");
        }
        // Check that all the CacheReferences (WeakCacheReferences) are null, since
        // they all should have been garbage collected.
        Map cache = getIdentityMap().getCacheKeys();
        for (Iterator iterator = cache.values().iterator(); iterator.hasNext(); ) {
            CacheKey key = (CacheKey)iterator.next();
            if (key.getObject() != null) {
                throw new TestErrorException("A WeakCacheKey with a non-empty WeakReference was found. The garbage collection did not clear the cache as expected.");
            }
        }
    }


}
