/**
 * Licensed to the Austrian Association for Software Tool Integration (AASTI)
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. The AASTI 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.openengsb.core.common;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

import org.junit.Test;
import org.openengsb.core.common.context.ContextHolder;
import org.openengsb.core.common.util.ThreadLocalUtil;

public class ThreadLocalUtilTest {

    @Test
    public void testInheritContext() throws Exception {
        ContextHolder.get().setCurrentContextId("0");
        ExecutorService pool = Executors.newSingleThreadExecutor();
        pool = ThreadLocalUtil.contextAwareExecutor(pool);
        final AtomicBoolean success = new AtomicBoolean(false);
        final AtomicReference<String> referenceContext = new AtomicReference<String>();
        referenceContext.set(ContextHolder.get().getCurrentContextId());
        Runnable command = new Runnable() {
            @Override
            public void run() {
                if (ContextHolder.get().getCurrentContextId() == referenceContext.get()) {
                    success.set(true);
                } else {
                    success.set(false);
                }
            }
        };
        pool.submit(command).get();

        ContextHolder.get().setCurrentContextId("1");
        referenceContext.set("1");

        pool.submit(command).get();
        assertThat(success.get(), is(true));
    }

    @Test
    public void testInvokeAll() throws Exception {
        ContextHolder.get().setCurrentContextId("0");
        ExecutorService pool = Executors.newSingleThreadExecutor();
        pool = ThreadLocalUtil.contextAwareExecutor(pool);
        final AtomicInteger success = new AtomicInteger(0);
        final AtomicReference<String> referenceContext = new AtomicReference<String>();
        referenceContext.set(ContextHolder.get().getCurrentContextId());
        Runnable command = new Runnable() {
            @Override
            public void run() {
                if (ContextHolder.get().getCurrentContextId() == referenceContext.get()) {
                    success.incrementAndGet();
                }
            }
        };
        pool.submit(command).get();

        ContextHolder.get().setCurrentContextId("1");
        referenceContext.set("1");

        Collection<Callable<Object>> commands = new ArrayList<Callable<Object>>();
        commands.add(Executors.callable(command));
        List<Future<Object>> invokeAll = pool.invokeAll(commands);
        invokeAll.get(0).get();

        assertThat(success.get(), is(2));
    }

    @Test
    public void testCallable() throws Exception {
        ContextHolder.get().setCurrentContextId("0");
        ExecutorService pool = Executors.newSingleThreadExecutor();
        pool = ThreadLocalUtil.contextAwareExecutor(pool);
        final AtomicReference<String> referenceContext = new AtomicReference<String>();
        referenceContext.set(ContextHolder.get().getCurrentContextId());
        Callable<Boolean> command = new Callable<Boolean>() {
            @Override
            public Boolean call() throws Exception {
                return ContextHolder.get().getCurrentContextId() == referenceContext.get();
            }
        };

        assertThat(pool.submit(command).get(), is(true));

        ContextHolder.get().setCurrentContextId("1");
        referenceContext.set("1");

        assertThat(pool.submit(command).get(), is(true));
    }
}

@@ -1338,16 +1338,41 @@
 rence;%0A%0A
+import org.junit.Before;%0A
 import o
@@ -1542,48 +1542,158 @@
     
-@Test%0A    public void testInheritContext
+private ExecutorService pool;%0A    private AtomicReference%3CString%3E referenceContext = new AtomicReference%3CString%3E();%0A%0A    @Before%0A    public void setup
 () t
@@ -1756,32 +1756,105 @@
 ContextId(%220%22);%0A
+        referenceContext.set(ContextHolder.get().getCurrentContextId());%0A
         Executor
@@ -1905,32 +1905,37 @@
 utor();%0A        
+this.
 pool = ThreadLoc
@@ -1977,226 +1977,138 @@
     
+%7D%0A%0A
     
-final AtomicBoolean success = new AtomicBoolean(false);%0A        final AtomicReference%3CString%3E referenceContext = new AtomicReference%3CString%3E();%0A        referenceContext.set(ContextHolder.get().getCurrentContextId()
+@Test%0A    public void testInheritContext() throws Exception %7B%0A        final AtomicBoolean success = new AtomicBoolean(false
 );%0A 
@@ -2730,399 +2730,57 @@
     
-ContextHolder.get().setCurrentContextId(%220%22);%0A        ExecutorService pool = Executors.newSingleThreadExecutor();%0A        pool = ThreadLocalUtil.contextAwareExecutor(pool);%0A        final AtomicInteger success = new AtomicInteger(0);%0A        final AtomicReference%3CString%3E referenceContext = new AtomicReference%3CString%3E();%0A        referenceContext.set(ContextHolder.get().getCurrentContextId()
+final AtomicInteger success = new AtomicInteger(0
 );%0A 
@@ -3531,350 +3531,8 @@
 n %7B%0A
-        ContextHolder.get().setCurrentContextId(%220%22);%0A        ExecutorService pool = Executors.newSingleThreadExecutor();%0A        pool = ThreadLocalUtil.contextAwareExecutor(pool);%0A        final AtomicReference%3CString%3E referenceContext = new AtomicReference%3CString%3E();%0A        referenceContext.set(ContextHolder.get().getCurrentContextId());%0A
     

refactor tests to make them more readable