/*
 * 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.*;
import org.eclipse.persistence.internal.helper.linkedlist.ExposedNodeLinkedList;
import org.eclipse.persistence.internal.identitymaps.*;
import org.eclipse.persistence.testing.framework.*;

/**
 * Test the SoftCacheIdentityMap.
 * This test will throws warnings on problem, not error because of VM differences.
 */
public class ReadSoftCacheWeakIdentityMapTest extends ReadWeakIdentityMapTest {
    public ReadSoftCacheWeakIdentityMapTest(Class<? extends IdentityMap> mapClass) {
        super(mapClass);
        setDescription("This test verifies that the SoftCacheWeakIdentityMap holds onto the SoftReferences appropriately");
    }

    @Override
    public void test() {
        if (getIdentityMap().getSize() == 0) {
            throw new TestWarningException("We did not fill the cache, the test is invalid.");
        }

        // Ensure subcache has correct references.
        ExposedNodeLinkedList list = ((SoftCacheWeakIdentityMap)getIdentityMap()).getReferenceCache();
        java.lang.ref.SoftReference ref = (java.lang.ref.SoftReference)list.getFirst();
        if (ref.get() == null) {
            throw new TestErrorException("Soft reference is null.");
        }
        ref = (java.lang.ref.SoftReference)list.getLast();
        if (ref.get() == null) {
            throw new TestErrorException("Soft reference is null.");
        }

        // 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(10000);
        for (int i = 0; i < 10000; ++i) {
            vector.addElement(new java.math.BigDecimal(i));
        }

        // Force garbage collection, which should clear the cache.
        System.gc();
        System.runFinalization();
        System.gc();
    }

    @Override
    public void verify() {
        // Ensure that some ref have garbage collected,
        // if not all through warning as different VM have different gc behavior.
        Map<Object, CacheKey> cache = getIdentityMap().getCacheKeys();
        int numObjects = 0;
        for (Iterator<CacheKey> iterator = cache.values().iterator(); iterator.hasNext();) {
            CacheKey key = iterator.next();
            if (key.getObject() != null) {
                numObjects++;
            }
        }
        if (numObjects == querySize) {
            throw new TestWarningException("The SoftCacheWeakIdentityMap did not allow any garbage collection. This could be a VM thing");
        } else if (numObjects < (getIdentityMap().getMaxSize() / 2)) {
            throw new TestWarningException("The SoftCacheWeakIdentityMap garbage collected the soft cache. This may be because of VM differences.");
        }
    }
}
