/*
 * Copyright (c) 2017, 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:
//     Tomas Kraus - 2017/10/11
//          Bug 525854 - Fix Java SE platform detection and clean up platform code
package org.eclipse.persistence.testing.tests.junit.helper;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.lang.reflect.Method;

import org.eclipse.persistence.internal.helper.JavaSEPlatform;
import org.eclipse.persistence.internal.helper.JavaVersion;
import org.eclipse.persistence.testing.framework.ReflectionHelper;
import org.junit.Test;

public class JavaVersionTest {

    /**
     * Check whether current Java has {@code Runtime.Version} class.
     * @return Value of {@code true} when current Java has {@code Runtime.Version} class or {@code false} otherwise.
     */
    private static boolean hasRuntimeVersion() {
        final Method[] methods = Runtime.class.getDeclaredMethods();
        for (final Method method : methods) {
            if ("version".equals(method.getName()) && method.getParameterCount() == 0) {
                return true;
            }
        }
        return false;
    }

    /**
     * Test Java version retrieval from {@code Runtime.Version}. It just calls {@code JavaVersion#runtimeVersion()} method
     * on current Java SE when {@literal >}9 and checks that no exception is thrown.
     */
    @Test
    public void testRuntimeVersion() {
        if (!hasRuntimeVersion()) {
            return;
        }
        try {
            final JavaVersion version =  ReflectionHelper.<JavaVersion>invokeStaticMethod("runtimeVersion", JavaVersion.class, null, JavaVersion.class);
            assertTrue("Minimal Java 9 required", version.getMajor() >= 9);
        } catch (ReflectiveOperationException e) {
            fail("Exception: " + e.getMessage());
        }
    }

    /**
     * Test Java version retrieval from {@code java.specification.version} system property. It just calls
     * {@code JavaVersion#propertyVersionParser(String)} method with current Java SE {@code java.specification.version}
     * system property value and checks that no exception is thrown.
     */
    @Test
    public void testPropertyVersion() {
        try {
            final String versionString = ReflectionHelper.<String>invokeStaticMethod(
                    "vmVersionString", JavaVersion.class, null, String.class);
            final JavaVersion version =  ReflectionHelper.<JavaVersion>invokeStaticMethod(
                    "propertyVersionParser", JavaVersion.class, new Class<?>[] {String.class}, JavaVersion.class, versionString);
        } catch (ReflectiveOperationException e) {
            fail("Exception: " + e.getMessage());
        }
    }

    /**
     * Verify Java version parser on set of valid and invalid {@code java.specification.version} system property values.
     * Because all version strings are in {@code [0-9]+'.'[0-9]+} format, parser shall always return {@code JavaVersion}
     * instance containing provided version numbers.
     */
    @Test
    public void testPropertyVersionParser() {
        // Verify valid pairs.
        for (final int [] version : JavaUtilTest.VALID) {
            final int major = version[0];
            final int minor = version[1];
            final String versionString = JavaSEPlatform.versionString(major, minor);
            try {
                final JavaVersion javaVersion =  ReflectionHelper.<JavaVersion>invokeStaticMethod(
                        "propertyVersionParser", JavaVersion.class, new Class<?>[] {String.class}, JavaVersion.class, versionString);
                assertNotNull("JavaVersion instance must be returned for valid platform"
                        +" version number ["+ major +","+ minor +"]", javaVersion);
                assertTrue("Returned JavaVersion instance numbers do not match provided"
                        + " version number ["+ major +","+ minor +"]", major == javaVersion.getMajor()
                        && minor == javaVersion.getMinor());
            } catch (ReflectiveOperationException e) {
                fail("Exception: " + e.getMessage());
            }
        }
        // Verify invalid pairs.
        for (final int [] version : JavaUtilTest.INVALID) {
            final int major = version[0];
            final int minor = version[1];
            final String versionString = JavaSEPlatform.versionString(major, minor);
            try {
                final JavaVersion javaVersion =  ReflectionHelper.<JavaVersion>invokeStaticMethod(
                        "propertyVersionParser", JavaVersion.class, new Class<?>[] {String.class}, JavaVersion.class, versionString);
                assertNotNull("JavaVersion instance must be returned for invalid platform"
                        +" version number ["+ major +","+ minor +"]", javaVersion);
                assertTrue("Returned JavaVersion instance numbers do not match provided"
                        + " version number ["+ major +","+ minor +"]", major == javaVersion.getMajor()
                        && minor == javaVersion.getMinor());
            } catch (ReflectiveOperationException e) {
                fail("Exception: " + e.getMessage());
            }
        }
    }

}
