content: /*
   * 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.aries.async.impl;
  
  import static org.junit.Assert.assertSame;
  import static org.junit.Assert.assertTrue;
  
  import java.util.concurrent.CountDownLatch;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.ScheduledExecutorService;
  import java.util.concurrent.TimeUnit;
  
  import org.junit.After;
  import org.junit.Before;
  import org.junit.Test;
  import org.junit.runner.RunWith;
  import org.mockito.Mock;
  import org.mockito.junit.MockitoJUnitRunner;
  import org.osgi.service.log.LogService;
  import org.osgi.util.function.Predicate;
  import org.osgi.util.promise.Promise;
  import org.osgi.util.promise.Success;
  import org.osgi.util.tracker.ServiceTracker;
  
  @RunWith(MockitoJUnitRunner.class)
  public class AsyncServiceTest {
  
  	public static class DelayedEcho {
  		public String echo(String s, int delay) {
  			try {
  				Thread.sleep(delay);
  			} catch (InterruptedException e) {
  				throw new RuntimeException("Thread interrupted", e);
  			}
  			if (s == null) throw new NullPointerException("Nothing to echo!");
  			return s;
  		}
  	}
  	
  	private ExecutorService es;
  	
  	private ScheduledExecutorService ses;
  	
  	@Mock
  	ServiceTracker<LogService, LogService> serviceTracker;
  	
  	@Before
  	public void start() {
  		es = Executors.newFixedThreadPool(3);
  		ses = Executors.newSingleThreadScheduledExecutor();
  	}
  
  	@After
  	public void stop() {
  		es.shutdownNow();
  		try {
  			es.awaitTermination(5, TimeUnit.SECONDS);
  		} catch (InterruptedException e) {
  			e.printStackTrace();
  		}
  
  		ses.shutdownNow();
  		try {
  			ses.awaitTermination(5, TimeUnit.SECONDS);
  		} catch (InterruptedException e) {
  			e.printStackTrace();
  		}
  	}
  	
  	
  	@Test
  	public void test() throws InterruptedException {
  		DelayedEcho raw = new DelayedEcho();
  		
  		AsyncService service = new AsyncService(null, es, ses,
  				serviceTracker);
  		
  		DelayedEcho mediated = service.mediate(raw, DelayedEcho.class);
  		
  		Promise<String> promise = service.call(mediated.echo("Hello World", 1000));
  		
  		final CountDownLatch latch = new CountDownLatch(1);
  		
  		promise.filter(new Predicate<String>() {
  				@Override
  				public boolean test(String t) {
  					return "Hello World".equals(t);
  				}
  			}).then(new Success<String, Void>() {
  				@Override
  				public Promise<Void> call(Promise<String> resolved)
  						throws Exception {
  					latch.countDown();
  					return null;
  				}
  			});
  		
  		assertTrue(latch.await(5, TimeUnit.SECONDS));
  	}
  
      @Test
      public void testMultipleMediationsCacheClassLoader() throws Exception {
          DelayedEcho raw = new DelayedEcho();
          
          AsyncService service = new AsyncService(null, es, ses,
                                                  serviceTracker);
          
          DelayedEcho mediated = service.mediate(raw, DelayedEcho.class);
          
          assertSame(mediated.getClass(), service.mediate(raw, DelayedEcho.class).getClass());
      }
  
      @Test
      public void testMultipleMediationsCacheClassLoaderInterface() throws Exception {
      	CharSequence raw = "test";
      	
      	AsyncService service = new AsyncService(null, es, ses,
      			serviceTracker);
      	
      	CharSequence mediated = service.mediate(raw, CharSequence.class);
      	
      	assertSame(mediated.getClass(), service.mediate(raw, CharSequence.class).getClass());
      }
      
  }
  