All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.evosuite.runtime.mock.java.lang.MockThread Maven / Gradle / Ivy

There is a newer version: 1.0.6
Show newest version
/**
 * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite
 * contributors
 *
 * This file is part of EvoSuite.
 *
 * EvoSuite is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3.0 of the License, or
 * (at your option) any later version.
 *
 * EvoSuite 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
 * Lesser Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with EvoSuite. If not, see .
 */
package org.evosuite.runtime.mock.java.lang;

import org.evosuite.runtime.annotation.EvoSuiteExclude;
import org.evosuite.runtime.RuntimeSettings;
import org.evosuite.runtime.mock.MockFramework;
import org.evosuite.runtime.mock.OverrideMock;
import org.evosuite.runtime.thread.ThreadCounter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Threads are very complex to handle.
 * For the moment, we mock only certain aspects: TODO
 *
 * Created by arcuri on 9/23/14.
 */
public class MockThread extends Thread implements OverrideMock {

    // ----- mock internals -------

    private static final Logger logger = LoggerFactory.getLogger(MockThread.class);

    private static final Map threadMap = new ConcurrentHashMap<>();

    public static void reset() {
        threadMap.clear();
    }

    private boolean isSutRelated() {
        String sut = RuntimeSettings.className;
        String threadName = this.getClass().getName();
        String targetName = target==null ? null : target.getClass().getName();

        /*
            Note: this check would not recognize code like:

            Thread t = new Thread(); t.start();

            however, as it does nothing, no point in starting it anyway
         */

        return  match(sut,threadName) || match(sut,targetName);
    }

    private boolean match(String sut, String other) {
        if(other==null || other.length() < sut.length()) {
            return false;
        }
        if(other.length() == sut.length()) {
            //is the thread the SUT itself?
            return other.equals(sut);
        } else {
            //anonymous or internal class of the SUT
            return other.startsWith(sut+"$");
        }
    }

    /**
     * a copy of the private field in superclass
     */
    private Runnable target;

    // ------ public static fields --------

    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;


    // ------ static  methods  --------

    public static Thread currentThread() {
        return Thread.currentThread();
    }

    @EvoSuiteExclude
    public static void yield() {
        Thread.yield();
    }

    @EvoSuiteExclude
    public static void sleep(long millis) throws InterruptedException {
        //no point in doing any sleep
        //MockThread.yield(); //just in case to change thread //FIXME quite a few side effects
        Thread.sleep(Math.min(millis,50)); //TODO maybe should be a parameter
    }

    @EvoSuiteExclude
    public static void sleep(long millis, int nanos)
            throws InterruptedException {
        MockThread.sleep(millis);
    }

    public static boolean interrupted() {
        return Thread.interrupted();
    }

    public static int activeCount() {
        return Thread.activeCount();
    }

    public static int enumerate(Thread tarray[]) {
        return Thread.enumerate(tarray);
    }

    public static void dumpStack() {
        if(!MockFramework.isEnabled()) {
            Thread.dumpStack();
        } else {
            new MockException("Stack trace").printStackTrace();
        }
    }

    public static Map getAllStackTraces() {
        if(!MockFramework.isEnabled()) {
            return Thread.getAllStackTraces();
        }
        //get actual running threads, and then replace stack traces

        //this will ask for permissions, but we grant it anyway
        Set threads =  Thread.getAllStackTraces().keySet();
        Map m = new HashMap<>(threads.size());
        for(Thread t : threads) {
            m.put(t,MockThrowable.getDefaultStackTrace());
        }

        return m;
    }

    public static boolean holdsLock(Object obj) {
        return Thread.holdsLock(obj);
    }

    public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        Thread.setDefaultUncaughtExceptionHandler(eh);
    }

    public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
        return Thread.getDefaultUncaughtExceptionHandler();
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

    // -------- constructors ---------

    public MockThread() {
        super();
        mockSetup(null);
    }

    public MockThread(Runnable target) {
        super(target);
        this.target = target;
        mockSetup(null);
    }

    public MockThread(ThreadGroup group, Runnable target) {
        super(group, target);
        this.target = target;
        mockSetup(null);
    }

    public MockThread(String name) {
        super(name);
        mockSetup(name);
    }

    public MockThread(ThreadGroup group, String name) {
        super(group, name);
        mockSetup(name);
    }

    public MockThread(Runnable target, String name) {
        super(target, name);
        this.target = target;
        mockSetup(name);
    }

    public MockThread(ThreadGroup group, Runnable target, String name) {
        super(group, target, name);
        this.target = target;
        mockSetup(name);
    }

    public MockThread(ThreadGroup group, Runnable target, String name,
                      long stackSize) {
        super(group, target, name, stackSize);
        this.target = target;
        mockSetup(name);
    }

    private void mockSetup(String name) {
        if(!MockFramework.isEnabled()) {
            return;
        }

        if(name == null) {
            /*
                If SUT did not specify any name, we need
                to change the one automatically given by the JVM,
                as it could be non-deterministic
             */
            setName("MockThread-"+getId());
        }
    }

    // ---------------

    @Override
    @EvoSuiteExclude
    public synchronized void start() {

        if(!MockFramework.isEnabled()) {
            super.start();
            return;
        }

        if(!isSutRelated()) {
            //no point in starting those 3rd party threads
            return;
        }

        ThreadCounter.getInstance().checkIfCanStartNewThread();

        /*
            TODO: we could rather buffer them like we did for hooks, and execute them at the end.
            We could even have methods in the test-cluster to execute some of those threads till they yield
            within the test case
         */
        super.start();
    }

    @Override
    public void run() {
        super.run();
    }

    @Override
    @EvoSuiteExclude
    public void interrupt() {
        super.interrupt();
    }


    @Override
    public boolean isInterrupted() {
        return super.isInterrupted();
    }

    @Override
    @EvoSuiteExclude
    public void destroy() {
        super.destroy();
    }



    @Override
    public String toString() {
        return super.toString();
    }

    @Override
    public ClassLoader getContextClassLoader() {
        return super.getContextClassLoader();
    }

    @Override
    public void setContextClassLoader(ClassLoader cl) {
        super.setContextClassLoader(cl);
    }

    @Override
    public StackTraceElement[] getStackTrace() {
        if(!MockFramework.isEnabled()) {
            return super.getStackTrace();
        }
        return MockThrowable.getDefaultStackTrace();
    }


    @Override
    public long getId() {
        if(!MockFramework.isEnabled()) {
            return super.getId();
        }

        synchronized (threadMap) {
            int identity = java.lang.System.identityHashCode(this);
            if (!threadMap.containsKey(identity)) {
                threadMap.put(identity, Long.valueOf(threadMap.size()));
            }
            return threadMap.get(identity);
        }
    }

    @Override
    public State getState() {
        return super.getState();
    }


    @Override
    public UncaughtExceptionHandler getUncaughtExceptionHandler() {
        return super.getUncaughtExceptionHandler();
    }

    @Override
    public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
        super.setUncaughtExceptionHandler(eh);
    }

    // ----- StaticReplacementMethods  ---------


    // Handled in the constructors
    // public final void setName(String name) {   }
    // public final String getName() {}


    //TODO
    // they are final
    /*public final void stop() {
        stop(new ThreadDeath());
    }
    public final synchronized void stop(Throwable obj) {
    ...
    }

    //public final native boolean isAlive();

    @Deprecated
    public final void suspend() {
        checkAccess();
        suspend0();
    }

    @Deprecated
    public final void resume() {
        checkAccess();
        resume0();
    }


    public final void setPriority(int newPriority) {
    }

    public final int getPriority() {
        return priority;
    }



    public final ThreadGroup getThreadGroup() {
        return group;
    }

    @Deprecated
    public native int countStackFrames();

    public final synchronized void join(long millis)
            throws InterruptedException {
    }

    public final synchronized void join(long millis, int nanos)
            throws InterruptedException {

    }

    public final void join() throws InterruptedException {
        join(0);
    }


    public final void setDaemon(boolean on) {
    }

    public final boolean isDaemon() {
        return daemon;
    }

    public final void checkAccess() {
    }
*/


}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy