/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to you under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.logging.log4j.message;

import org.apache.logging.log4j.util.Timer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.parallel.ResourceAccessMode;
import org.junit.jupiter.api.parallel.ResourceLock;
import org.junit.jupiter.api.parallel.Resources;

/**
 *
 */
@Tag("performance")
@ResourceLock(value = Resources.LOCALE, mode = ResourceAccessMode.READ)
public class MessageFormatsPerfTest {

    private static final int LOOP_CNT = 500;
    String[] array = new String[LOOP_CNT];
    private static long stringTime = 0;
    private static long paramTime = 0;
    private static long msgFormatTime = 0;
    private static long formattedTime = 0;

    @AfterAll
    public static void after() {
        if (stringTime > paramTime) {
            System.out.println(String.format("Parameterized is %1$.2f times faster than StringFormat.",
                ((float) stringTime / paramTime)));
        } else if (stringTime < paramTime) {
            System.out.println(String.format("Parameterized is %1$.2f times slower than StringFormat.",
                ((float) paramTime / stringTime)));
        } else {
            System.out.println("The speed of Parameterized and StringFormat are the same");
        }
        if (msgFormatTime > paramTime) {
            System.out.println(String.format("Parameterized is %1$.2f times faster than MessageFormat.",
                ((float) msgFormatTime / paramTime)));
        } else if (msgFormatTime < paramTime) {
            System.out.println(String.format("Parameterized is %1$.2f times slower than MessageFormat.",
                ((float) paramTime / msgFormatTime)));
        } else {
            System.out.println("The speed of Parameterized and MessageFormat are the same");
        }
        if (formattedTime > paramTime) {
            System.out.println(String.format("Parameterized is %1$.2f times faster than Formatted.",
                ((float) formattedTime / paramTime)));
        } else if (formattedTime < paramTime) {
            System.out.println(String.format("Parameterized is %1$.2f times slower than Formatted.",
                ((float) paramTime / formattedTime)));
        } else {
            System.out.println("The speed of Parameterized and Formatted are the same");
        }
    }

    @Test
    public void testStringPerf() {
        final String testMsg = "Test message %1s %2s";
        final Timer timer = new Timer("StringFormat", LOOP_CNT);
        timer.start();
        for (int i = 0; i < LOOP_CNT; ++i) {
            final StringFormattedMessage msg = new StringFormattedMessage(testMsg, "Apache", "Log4j");
            array[i] = msg.getFormattedMessage();
        }
        timer.stop();
        stringTime = timer.getElapsedNanoTime();
        System.out.println(timer.toString());
    }

    @Test
    public void testMessageFormatPerf() {
        final String testMsg = "Test message {0} {1}";
        final Timer timer = new Timer("MessageFormat", LOOP_CNT);
        timer.start();
        for (int i = 0; i < LOOP_CNT; ++i) {
            final MessageFormatMessage msg = new MessageFormatMessage(testMsg, "Apache", "Log4j");
            array[i] = msg.getFormattedMessage();
        }
        timer.stop();
        msgFormatTime = timer.getElapsedNanoTime();
        System.out.println(timer.toString());
    }

    @Test
    public void testParameterizedPerf() {
        final String testMsg = "Test message {} {}";
        final Timer timer = new Timer("Parameterized", LOOP_CNT);
        timer.start();
        for (int i = 0; i < LOOP_CNT; ++i) {
            final ParameterizedMessage msg = new ParameterizedMessage(testMsg, "Apache", "Log4j");
            array[i] = msg.getFormattedMessage();
        }
        timer.stop();
        paramTime = timer.getElapsedNanoTime();
        System.out.println(timer.toString());
    }

    @Test
    public void testFormattedParameterizedPerf() {
        final String testMsg = "Test message {} {}";
        final Timer timer = new Timer("FormattedParameterized", LOOP_CNT);
        timer.start();
        for (int i = 0; i < LOOP_CNT; ++i) {
            final FormattedMessage msg = new FormattedMessage(testMsg, "Apache", "Log4j");
            array[i] = msg.getFormattedMessage();
        }
        timer.stop();
        formattedTime = timer.getElapsedNanoTime();
        System.out.println(timer.toString());
    }
}
