/*
 * Copyright (c) 2008-2013, Hazelcast, Inc. All Rights Reserved.
 *
 * Licensed 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 com.hazelcast.test;

import com.hazelcast.test.annotation.Repeat;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

import java.lang.reflect.Method;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * User: ahmetmircik
 * Date: 11/27/13
 */
public abstract class AbstractHazelcastClassRunner extends BlockJUnit4ClassRunner {

    static {
        final String logging = "hazelcast.logging.type";
        System.setProperty(logging, "log4j2");
        if (System.getProperty(logging) == null) {
            System.setProperty(logging, "log4j2");
        }
        if (System.getProperty(TestEnvironment.HAZELCAST_TEST_USE_NETWORK) == null) {
            System.setProperty(TestEnvironment.HAZELCAST_TEST_USE_NETWORK, "false");
        }
        System.setProperty("hazelcast.version.check.enabled", "false");
        System.setProperty("hazelcast.mancenter.enabled", "false");
        System.setProperty("hazelcast.wait.seconds.before.join", "1");
        System.setProperty("hazelcast.local.localAddress", "127.0.0.1");
        System.setProperty("java.net.preferIPv4Stack", "true");

        // randomize multicast group...
        Random rand = new Random();
        int g1 = rand.nextInt(255);
        int g2 = rand.nextInt(255);
        int g3 = rand.nextInt(255);
        System.setProperty("hazelcast.multicast.group", "224." + g1 + "." + g2 + "." + g3);
    }

    /**
     * Creates a BlockJUnit4ClassRunner to run {@code klass}
     *
     * @throws org.junit.runners.model.InitializationError if the test class is malformed.
     */
    public AbstractHazelcastClassRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List<FrameworkMethod> getChildren() {
        final List<FrameworkMethod> children = super.getChildren();
        Collections.shuffle(children);
        return children;
    }

    @Override
    protected Statement methodBlock(FrameworkMethod method) {
        final Statement statement = super.methodBlock(method);
        final Repeat repeatable = getRepeatable(method);
        if (repeatable == null || repeatable.value() < 2) {
            return statement;
        }
        return new TestRepeater(statement, method.getMethod(), repeatable.value());
    }

    /**
     * Gets repeat annotation, if any.
     * Method level definition overrides class level definition.
     */
    private Repeat getRepeatable(FrameworkMethod method) {
        Repeat repeatable = method.getAnnotation(Repeat.class);
        if (repeatable == null) {
            repeatable = super.getTestClass().getJavaClass().getAnnotation(Repeat.class);
        }
        return repeatable;
    }

    private class TestRepeater extends Statement {

        private final Statement statement;

        private final Method testMethod;

        private final int repeat;

        public TestRepeater(Statement statement, Method testMethod, int repeat) {
            this.statement = statement;
            this.testMethod = testMethod;
            this.repeat = Math.max(1, repeat);
        }

        /**
         * Invokes the next {@link Statement statement} in the execution chain for
         * the specified repeat count.
         */
        @Override
        public void evaluate() throws Throwable {
            for (int i = 0; i < repeat; i++) {
                if (repeat > 1) {
                    System.out.println(String.format("---> Repeating test [%s:%s], run count [%d]",
                            testMethod.getDeclaringClass().getCanonicalName(),
                            testMethod.getName(), i + 1));
                }
                statement.evaluate();
            }
        }
    }
}

@@ -1204,55 +1204,8 @@
 e%22;%0A
-        System.setProperty(logging, %22log4j2%22);%0A
     
@@ -1297,17 +1297,16 @@
 , %22log4j
-2
 %22);%0A    

Fix logging setup for tests