/*
 * Copyright (c) 2015, 2019, 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.
 */

/*
 * @test
 * @summary Unit test for java.lang.Runtime.Version
 * @bug 8072379 8144062 8161236 8160956 8194879
 */

import java.lang.Runtime.Version;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import static java.lang.System.out;

public class Basic {

    private static final Class<? extends Throwable> IAE
        = IllegalArgumentException.class;
    private static final Class<? extends Throwable> NPE
        = NullPointerException.class;
    private static final Class<? extends Throwable> NFE
        = NumberFormatException.class;

    private static final BigInteger TOO_BIG
        = (BigInteger.valueOf(Integer.MAX_VALUE)).add(BigInteger.ONE);
    private static final String TOO_BIG_STR = TOO_BIG.toString();

    public static void main(String ... args) {

        //// Tests for parse(), feature(), interim(), update(), patch(),
        //// pre(), build(), optional(), version(), and toString()
        //   v                          f     i  u  p pre bld opt

        // $VNUM
        test("9",                       9,    0, 0, 0, "", 0, "");
        test("9.1",                     9,    1, 0, 0, "", 0, "");
        test("9.0.1",                   9,    0, 1, 0, "", 0, "");
        test("9.0.0.1",                 9,    0, 0, 1, "", 0, "");
        test("9.0.0.0.1",               9,    0, 0, 0, "", 0, "");
        test("404.1.2",                 404,  1, 2, 0, "", 0, "");
        test("9.1.2.3",                 9,    1, 2, 3, "", 0, "");
        test("1000.0.0.0.0.0.99999999", 1000, 0, 0, 0, "", 0, "");

        tryCatch(null,    NPE);
        tryCatch("",      IAE);
        tryCatch("foo",   IAE);
        tryCatch("7a",    IAE);
        tryCatch("0",     IAE);
        tryCatch("09",    IAE);
        tryCatch("9.0",   IAE);
        tryCatch("9.0.",  IAE);
        tryCatch("1.9,1", IAE);
        tryCatch(TOO_BIG_STR, NFE);

        // $PRE
        test("9-ea",       9, 0, 0, 0, "ea",       0, "");
        test("9-internal", 9, 0, 0, 0, "internal", 0, "");
        test("9-0",        9, 0, 0, 0, "0",        0, "");
        test("9.2.7-8",    9, 2, 7, 0, "8",        0, "");
        test("1-ALL",      1, 0, 0, 0, "ALL",      0, "");
        test("2.3.4.5-1a", 2, 3, 4, 5, "1a",       0, "");
        test("1-" + TOO_BIG_STR, 1, 0, 0, 0, TOO_BIG_STR, 0, "");

        tryCatch("9:-ea",     IAE);
        tryCatch("3.14159-",  IAE);
        tryCatch("3.14159-%", IAE);

        // $BUILD
        test("9+0",            9, 0,  0,  0, "",      0,       "");
        test("3.14+9999900",   3, 14, 0,  0, "",      9999900, "");
        test("9-pre+105",      9, 0,  0,  0, "pre",   105,     "");
        test("6.0.42-8beta+4", 6, 0,  42, 0, "8beta", 4,       "");

        tryCatch("9+",     IAE);
        tryCatch("7+a",    IAE);
        tryCatch("9+00",   IAE);
        tryCatch("4.2+01", IAE);
        tryCatch("4.2+1a", IAE);
        tryCatch("1+" + TOO_BIG_STR, NFE);

        // $OPT
        test("9+-foo",          9,   0, 0, 0, "",       0,  "foo");
        test("9-pre-opt",       9,   0, 0, 0, "pre",    0,  "opt");
        test("42+---bar",       42,  0, 0, 0, "",       0,  "--bar");
        test("2.91+-8061493-",  2,  91, 0, 0, "",       0,  "8061493-");
        test("24+-foo.bar",     24,  0, 0, 0, "",       0,  "foo.bar");
        test("9-ribbit+17-...", 9,   0, 0, 0, "ribbit", 17, "...");
        test("7+1-" + TOO_BIG_STR, 7,0, 0, 0, "",       1,  TOO_BIG_STR);

        tryCatch("9-pre+-opt", IAE);
        tryCatch("1.4142+-",   IAE);
        tryCatch("2.9979+-%",  IAE);
        tryCatch("10--ea",     IAE);

        //// Test for Runtime.version()
        testVersion();

        //// Test for equals{IgnoreOptional}?(), hashCode(),
        //// compareTo{IgnoreOptional}?()
        // compare: after "<" == -1, equal == 0, before ">" == 1
        //      v0            v1                  eq     eqNO  cmp  cmpNO
        testEHC("9",          "9",                true,  true,   0,    0);

        testEHC("8",          "9",                false, false, -1,   -1);
        testEHC("9",          "10",               false, false, -1,   -1);
        testEHC("9",          "8",                false, false,  1,    1);

        testEHC("10.512.1",   "10.512.2",         false, false, -1,   -1);
        testEHC("10.512.0.1", "10.512.0.2",       false, false, -1,   -1);
        testEHC("10.512.0.0.1", "10.512.0.0.2",   false, false, -1,   -1);
        testEHC("512.10.1",   "512.11.1",         false, false, -1,   -1);

        // $OPT comparison
        testEHC("9",          "9+-oink",          false, true,  -1,    0);
        testEHC("9+-ribbit",  "9+-moo",           false, true,   1,    0);
        testEHC("9-quack+3-ribbit",
                              "9-quack+3-moo",    false, true,   1,    0);
        testEHC("9.1+7",      "9.1+7-moo-baa-la", false, true,  -1,    0);

        // numeric vs. non-numeric $PRE
        testEHC("9.1.1.2-2a", "9.1.1.2-12",       false, false,  1,    1);
        testEHC("9.1.1.2-12", "9.1.1.2-4",        false, false,  1,    1);

        testEHC("27.16",      "27.16+120",        false, false, -1,   -1);
        testEHC("10",         "10-ea",            false, false,  1,    1);
        testEHC("10.1+1",     "10.1-ea+1",        false, false,  1,    1);
        testEHC("10.0.1+22",  "10.0.1+21",        false, false,  1,    1);

        // numeric vs. non-numeric $PRE
        testEHC("9.1.1.2-12", "9.1.1.2-a2",       false, false, -1,   -1);
        testEHC("9.1.1.2-1",  "9.1.1.2-4",        false, false, -1,   -1);

        testEHC("9-internal", "9",                false, false, -1,   -1);
        testEHC("9-ea+120",   "9+120",            false, false, -1,   -1);
        testEHC("9-ea+120",   "9+120",            false, false, -1,   -1);
        testEHC("9+101",      "9",                false, false,  1,    1);
        testEHC("9+101",      "9+102",            false, false, -1,   -1);
        testEHC("1.9-ea",     "9-ea",             false, false, -1,   -1);

        if (fail != 0)
            throw new RuntimeException((fail + pass) + " tests: "
                                       + fail + " failure(s), first", first);
        else
            out.println("all " + (fail + pass) + " tests passed");

    }

    private static void test(String s, Integer feature, Integer interim,
                             Integer update, Integer patch,
                             String pre, Integer build, String opt)
    {
        Version v = testParse(s);

        testStr(v.toString(), s);

        testInt(v.feature(), feature);
        testInt(v.major(), feature);
        testInt(v.interim(), interim);
        testInt(v.minor(), interim);
        testInt(v.update(), update);
        testInt(v.security(), update);
        testInt(v.patch(), patch);
        testStr((v.pre().isPresent() ? v.pre().get() : ""), pre);
        testInt((v.build().isPresent() ? v.build().get() : 0), build);
        testStr((v.optional().isPresent() ? v.optional().get() : ""), opt);

        testVersion(v.version(), s);
    }

    private static Version testParse(String s) {
        Version v = Version.parse(s);
        pass();
        return v;
    }

    private static void testInt(int got, int exp) {
        if (got != exp) {
            fail("testInt()", Integer.toString(exp), Integer.toString(got));
        } else {
            pass();
        }
     }

    private static void testStr(String got, String exp) {
        if (!got.equals(exp)) {
            fail("testStr()", exp, got);
        } else {
            pass();
        }
    }

    private static void tryCatch(String s, Class<? extends Throwable> ex) {
        Throwable t = null;
        try {
            Version.parse(s);
        } catch (Throwable x) {
            if (ex.isAssignableFrom(x.getClass())) {
                t = x;
            } else
                x.printStackTrace();
        }
        if ((t == null) && (ex != null))
            fail(s, ex);
        else
            pass();
    }

    private static void testVersion() {
        Version current = Runtime.version();
        String javaVer = System.getProperty("java.runtime.version");

        // java.runtime.version == $VNUM(\-$PRE)?(\+$BUILD)?(-$OPT)?
        String [] jv  = javaVer.split("\\+");
        String [] ver = jv[0].split("-");
        List<Integer> javaVerVNum
            = Arrays.stream(ver[0].split("\\."))
            .map(Integer::parseInt)
            .collect(Collectors.toList());
        if (!javaVerVNum.equals(current.version())) {
            fail("Runtime.version()", javaVerVNum.toString(),
                 current.version().toString());
        } else {
            pass();
        }

        Optional<String> javaVerPre
            = (ver.length >= 2)
            ? Optional.ofNullable(ver[1])
            : Optional.empty();
        if (!javaVerPre.equals(current.pre())) {
            fail("testCurrent() pre()", javaVerPre.toString(),
                 current.pre().toString());
        } else {
            pass();
        }

        testEHC(current.toString(), javaVer, true, true, 0, 0);
    }

    private static void testVersion(List<Integer> vnum, String s) {
        List<Integer> svnum = new ArrayList<>();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < s.length(); i++) {
            Character c = s.charAt(i);
            if (Character.isDigit(c)) {
                sb.append(c);
            } else {
                svnum.add(Integer.parseInt(sb.toString()));
                sb = new StringBuilder();
                if (c == '+' || c == '-') {
                    break;
                }
            }
        }
        if (sb.length() > 0) {
            svnum.add(Integer.parseInt(sb.toString()));
        }

        if (!svnum.equals(vnum)) {
            fail("testVersion() equals()", svnum.toString(), vnum.toString());
        } else {
            pass();
        }
    }

    private static void testEHC(String s0, String s1, boolean eq, boolean eqNO,
                                int cmp, int cmpNO)
    {
        Version v0 = Version.parse(s0);
        Version v1 = Version.parse(s1);

        testEquals(v0, v1, eq);
        testEqualsNO(v0, v1, eqNO);

        testHashCode(v0, v1, eq);

        testCompare(v0, v1, cmp);
        testCompareNO(v0, v1, cmpNO);
    }

    private static void testEqualsNO(Version v0, Version v1, boolean eq) {
        if (eq == v0.equalsIgnoreOptional(v1)) {
            pass();
        } else {
            fail("equalsIgnoreOptional() " + Boolean.toString(eq),
                 v0.toString(), v1.toString());
        }
    }

    private static void testEquals(Version v0, Version v1, boolean eq) {
        if (eq == v0.equals(v1)) {
            pass();
        } else {
            fail("equals() " + Boolean.toString(eq),
                 v0.toString(), v1.toString());
        }
    }

    private static void testHashCode(Version v0, Version v1, boolean eq) {
        int h0 = v0.hashCode();
        int h1 = v1.hashCode();
        if (eq) {
            testInt(h0, h1);
        } else if (h0 == h1) {
            fail(String.format("hashCode() %s", h0),
                 Integer.toString(h0),
                 Integer.toString(h1));
        } else { // !eq && (h0 != h1)
            pass();
        }
    }

    private static void testCompareNO(Version v0, Version v1, int compare) {
        int cmp = v0.compareToIgnoreOptional(v1);
        checkCompare(v0, v1, compare, cmp);
    }

    private static void testCompare(Version v0, Version v1, int compare) {
        int cmp = v0.compareTo(v1);
        checkCompare(v0, v1, compare, cmp);
    }

    private static void checkCompare(Version v0, Version v1,
                                     int expected, int actual)
    {
        if (Integer.signum(expected) == Integer.signum(actual)) {
            pass();
        } else {
            fail(String.format("compare() (actual = %s) (expected = %s)",
                               actual, expected),
                 v0.toString(), v1.toString());
        }
    }

    private static int fail = 0;
    private static int pass = 0;

    private static Throwable first;

    static void pass() {
        pass++;
    }

    static void fail(String fs, Class ex) {
        String s = "'" + fs + "'";
        if (ex != null)
            s += ": " + ex.getName() + " not thrown";
        if (first == null)
            setFirst(s);
        System.err.println("FAILED: " + s);
        fail++;
    }

    static void fail(String t, String exp, String got) {
        String s = t + ": Expected '" + exp + "', got '" + got + "'";
        if (first == null)
            setFirst(s);
        System.err.println("FAILED: " + s);
        fail++;
     }

    private static void setFirst(String s) {
        try {
            throw new RuntimeException(s);
        } catch (RuntimeException x) {
            first = x;
        }
    }

}
