Package com.opengamma.core.security.impl

Source Code of com.opengamma.core.security.impl.CoalescingSecuritySourceTest

/**
* Copyright (C) 2012 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.core.security.impl;

import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertSame;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;

import java.util.Arrays;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.mockito.Mockito;
import org.testng.annotations.Test;

import com.google.common.collect.Maps;
import com.opengamma.OpenGammaRuntimeException;
import com.opengamma.core.security.Security;
import com.opengamma.core.security.SecuritySource;
import com.opengamma.core.security.impl.test.MockSecuritySource;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.ObjectId;
import com.opengamma.id.UniqueId;
import com.opengamma.id.VersionCorrection;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.test.Timeout;

/**
* Tests the {@link CoalescingSecuritySource} class.
*/
@Test(groups = TestGroup.INTEGRATION)
public class CoalescingSecuritySourceTest {

  private static void join(final CyclicBarrier barrier) {
    try {
      barrier.await(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
    } catch (Exception e) {
      throw new OpenGammaRuntimeException("interrupted", e);
    }
  }

  private static void sleep() {
    try {
      Thread.sleep(Timeout.standardTimeoutMillis() / 4);
    } catch (InterruptedException e) {
      throw new OpenGammaRuntimeException("interrupted", e);
    }
  }

  public void testGetSecurity_byUniqueId_a() throws Exception {
    final UniqueId uidA = UniqueId.of("Test", "A");
    final Security secA = Mockito.mock(Security.class);
    final UniqueId uidB = UniqueId.of("Test", "B");
    final Security secB = Mockito.mock(Security.class);
    final UniqueId uidC = UniqueId.of("Test", "C");
    final Security secC = Mockito.mock(Security.class);
    final CyclicBarrier barrier = new CyclicBarrier(4);
    final MockSecuritySource underlying = new MockSecuritySource() {

      int _state;

      @Override
      public Security get(final UniqueId uid) {
        assertEquals(_state++, 0);
        join(barrier); //1
        assertEquals(uid, uidA);
        // Pause for a bit to make sure that the other threads get blocked in their getSecurity methods
        sleep();
        return secA;
      }

      @Override
      public Map<UniqueId, Security> get(final Collection<UniqueId> uids) {
        assertEquals(_state++, 1);
        assertEquals(uids.size(), 2);
        assertTrue(uids.contains(uidB));
        assertTrue(uids.contains(uidC));
        final Map<UniqueId, Security> result = Maps.newHashMapWithExpectedSize(2);
        result.put(uidB, secB);
        result.put(uidC, secC);
        return result;
      }

    };
    final CoalescingSecuritySource coalescing = new CoalescingSecuritySource(underlying);
    // Start three threads. One will do the first write, the other two will be blocked. Then one of the other two will do a second
    // write that includes that required by the third. The third will do no I/O itself.
    final ExecutorService exec = Executors.newCachedThreadPool();
    try {
      final Future<?> a = exec.submit(new Runnable() {
        @Override
        public void run() {
          final Security s = coalescing.get(uidA);
          assertSame(s, secA);
        }
      });
      final Future<?> b = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier);
          final Security s = coalescing.get(uidB);
          assertSame(s, secB);
        }
      });
      final Future<?> c = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier);
          final Security s = coalescing.get(uidC);
          assertSame(s, secC);
        }
      });
      join(barrier);
      a.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      b.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      c.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
    } finally {
      exec.shutdownNow();
    }
  }

  public void testGetSecurity_byUniqueId_b() throws Exception {
    final UniqueId uidA = UniqueId.of("Test", "A");
    final Security secA = Mockito.mock(Security.class);
    final UniqueId uidB = UniqueId.of("Test", "B");
    final Security secB = Mockito.mock(Security.class);
    final UniqueId uidC = UniqueId.of("Test", "C");
    final Security secC = Mockito.mock(Security.class);
    final CyclicBarrier barrier1 = new CyclicBarrier(3);
    final CyclicBarrier barrier2 = new CyclicBarrier(2);
    final MockSecuritySource underlying = new MockSecuritySource() {

      int _state;

      @Override
      public Security get(final UniqueId uid) {
        assertEquals(_state++, 0);
        join(barrier1);
        assertEquals(uid, uidA);
        // Pause for a bit to make sure that the other thread gets blocked in their getSecurity methods
        sleep();
        return secA;
      }

      @Override
      public Map<UniqueId, Security> get(final Collection<UniqueId> uids) {
        assertEquals(_state++, 1);
        assertEquals(uids.size(), 2);
        assertTrue(uids.contains(uidB));
        assertTrue(uids.contains(uidC));
        final Map<UniqueId, Security> result = Maps.newHashMapWithExpectedSize(2);
        result.put(uidB, secB);
        result.put(uidC, secC);
        return result;
      }

    };
    final CoalescingSecuritySource coalescing = new CoalescingSecuritySource(underlying) {
      @Override
      protected void releaseOtherWritingThreads() {
        join(barrier2); // 1 + 2 // release the third thread
      }
    };
    // Start two threads. One will do the first write, the other will be blocked. Suppressing releaseOtherThreads means a third
    // call will try to write its own value plus those from the other threads. The second thread will do no I/O itself.
    final ExecutorService exec = Executors.newCachedThreadPool();
    try {
      final Future<?> a = exec.submit(new Runnable() {
        @Override
        public void run() {
          final Security s = coalescing.get(uidA);
          assertSame(s, secA);
        }
      });
      final Future<?> b = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier1);
          final Security s = coalescing.get(uidB);
          assertSame(s, secB);
        }
      });
      final Future<?> c = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier2); // 1
          final Security s = coalescing.get(uidC);
          assertSame(s, secC);
        }
      });
      join(barrier1);
      a.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      b.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      join(barrier2); // 2
      c.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
    } finally {
      exec.shutdownNow();
    }
  }

  public void testGetSecurities_byUniqueId_a() throws Exception {
    final UniqueId uidA = UniqueId.of("Test", "A");
    final Security secA = Mockito.mock(Security.class);
    final UniqueId uidB = UniqueId.of("Test", "B");
    final Security secB = Mockito.mock(Security.class);
    final UniqueId uidC = UniqueId.of("Test", "C");
    final Security secC = Mockito.mock(Security.class);
    final CyclicBarrier barrier = new CyclicBarrier(4);
    final MockSecuritySource underlying = new MockSecuritySource() {

      int _state;

      @Override
      public Map<UniqueId, Security> get(final Collection<UniqueId> uids) {
        final Map<UniqueId, Security> result = Maps.newHashMapWithExpectedSize(uids.size());
        if (++_state == 1) {
          assertEquals(uids.size(), 2);
          join(barrier);
          assertTrue(uids.contains(uidA));
          assertTrue(uids.contains(uidB));
          result.put(uidA, secA);
          result.put(uidB, secB);
          // Pause for a bit to make sure that the other threads get blocked in their getSecurity methods
          sleep();
        } else if (_state == 2) {
          assertEquals(uids.size(), 3);
          assertTrue(uids.contains(uidA));
          assertTrue(uids.contains(uidB));
          assertTrue(uids.contains(uidC));
          result.put(uidA, secA);
          result.put(uidB, secB);
          result.put(uidC, secC);
        } else {
          fail();
        }
        return result;
      }

    };
    final CoalescingSecuritySource coalescing = new CoalescingSecuritySource(underlying);
    // Start three threads. One will do the first write, the other two will be blocked. Then one of the other two will do a second
    // write that includes that required by the third. The third will do no I/O itself.
    final ExecutorService exec = Executors.newCachedThreadPool();
    try {
      final Future<?> a = exec.submit(new Runnable() {
        @Override
        public void run() {
          final Map<UniqueId, Security> result = coalescing.get(Arrays.asList(uidA, uidB));
          assertEquals(result.size(), 2);
          assertSame(result.get(uidA), secA);
          assertSame(result.get(uidB), secB);
        }
      });
      final Future<?> b = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier);
          final Map<UniqueId, Security> result = coalescing.get(Arrays.asList(uidA, uidC));
          assertEquals(result.size(), 2);
          assertSame(result.get(uidA), secA);
          assertSame(result.get(uidC), secC);
        }
      });
      final Future<?> c = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier);
          final Map<UniqueId, Security> result = coalescing.get(Arrays.asList(uidB, uidC));
          assertEquals(result.size(), 2);
          assertSame(result.get(uidB), secB);
          assertSame(result.get(uidC), secC);
        }
      });
      join(barrier);
      a.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      b.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      c.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
    } finally {
      exec.shutdownNow();
    }
  }

  public void testGetSecurities_byUniqueId_b() throws Exception {
    final UniqueId uidA = UniqueId.of("Test", "A");
    final Security secA = Mockito.mock(Security.class);
    final UniqueId uidB = UniqueId.of("Test", "B");
    final Security secB = Mockito.mock(Security.class);
    final UniqueId uidC = UniqueId.of("Test", "C");
    final Security secC = Mockito.mock(Security.class);
    final CyclicBarrier barrier1 = new CyclicBarrier(3);
    final CyclicBarrier barrier2 = new CyclicBarrier(2);
    final MockSecuritySource underlying = new MockSecuritySource() {

      int _state;

      @Override
      public Map<UniqueId, Security> get(final Collection<UniqueId> uids) {
        final Map<UniqueId, Security> result = Maps.newHashMapWithExpectedSize(uids.size());
        if (++_state == 1) {
          assertEquals(uids.size(), 2);
          join(barrier1);
          assertTrue(uids.contains(uidA));
          assertTrue(uids.contains(uidB));
          result.put(uidA, secA);
          result.put(uidB, secB);
          // Pause for a bit to make sure that the other threads get blocked in their getSecurity methods
          sleep();
        } else if (_state == 2) {
          assertEquals(uids.size(), 3);
          assertTrue(uids.contains(uidA));
          assertTrue(uids.contains(uidB));
          assertTrue(uids.contains(uidC));
          result.put(uidA, secA);
          result.put(uidB, secB);
          result.put(uidC, secC);
        } else {
          fail();
        }
        return result;
      }

    };
    final CoalescingSecuritySource coalescing = new CoalescingSecuritySource(underlying) {
      @Override
      protected void releaseOtherWritingThreads() {
        join(barrier2); // 1 + 2 // release the third thread
      }
    };
    // Start two threads. One will do the first write, the other will be blocked. Suppressing releaseOtherThreads means a third
    // call will try to write its own value plus those from the other threads. The second thread will do no I/O itself.
    final ExecutorService exec = Executors.newCachedThreadPool();
    try {
      final Future<?> a = exec.submit(new Runnable() {
        @Override
        public void run() {
          final Map<UniqueId, Security> result = coalescing.get(Arrays.asList(uidA, uidB));
          assertEquals(result.size(), 2);
          assertSame(result.get(uidA), secA);
          assertSame(result.get(uidB), secB);
        }
      });
      final Future<?> b = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier1);
          final Map<UniqueId, Security> result = coalescing.get(Arrays.asList(uidA, uidC));
          assertEquals(result.size(), 2);
          assertSame(result.get(uidA), secA);
          assertSame(result.get(uidC), secC);
        }
      });
      final Future<?> c = exec.submit(new Runnable() {
        @Override
        public void run() {
          join(barrier2); //1
          final Map<UniqueId, Security> result = coalescing.get(Arrays.asList(uidB, uidC));
          assertEquals(result.size(), 2);
          assertSame(result.get(uidB), secB);
          assertSame(result.get(uidC), secC);
        }
      });
      join(barrier1);
      a.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      b.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
      join(barrier2); // 1 + 2
      c.get(Timeout.standardTimeoutMillis(), TimeUnit.MILLISECONDS);
    } finally {
      exec.shutdownNow();
    }
  }

  public void testGetSecurity_byObjectId() {
    final SecuritySource underlying = Mockito.mock(SecuritySource.class);
    final SecuritySource coalescing = new CoalescingSecuritySource(underlying);
    coalescing.get(ObjectId.of("Test", "Test"), VersionCorrection.LATEST);
    Mockito.verify(underlying).get(ObjectId.of("Test", "Test"), VersionCorrection.LATEST);
  }

  public void testGetSecurities_byExternalIdBundleVersionCorrection() {
    final SecuritySource underlying = Mockito.mock(SecuritySource.class);
    final SecuritySource coalescing = new CoalescingSecuritySource(underlying);
    coalescing.get(ExternalIdBundle.EMPTY, VersionCorrection.LATEST);
    Mockito.verify(underlying).get(ExternalIdBundle.EMPTY, VersionCorrection.LATEST);
  }

  public void testGetSecurities_byExternalIdBundle() {
    final SecuritySource underlying = Mockito.mock(SecuritySource.class);
    final SecuritySource coalescing = new CoalescingSecuritySource(underlying);
    coalescing.get(ExternalIdBundle.EMPTY);
    Mockito.verify(underlying).get(ExternalIdBundle.EMPTY);
  }

  public void testGetSecurity_byExternalIdBundle() {
    final SecuritySource underlying = Mockito.mock(SecuritySource.class);
    final SecuritySource coalescing = new CoalescingSecuritySource(underlying);
    coalescing.get(ExternalIdBundle.EMPTY);
    Mockito.verify(underlying).get(ExternalIdBundle.EMPTY);
  }

  public void testGetSecurity_byExternalIdBundleVersionCorrection() {
    final SecuritySource underlying = Mockito.mock(SecuritySource.class);
    final SecuritySource coalescing = new CoalescingSecuritySource(underlying);
    coalescing.get(ExternalIdBundle.EMPTY, VersionCorrection.LATEST);
    Mockito.verify(underlying).get(ExternalIdBundle.EMPTY, VersionCorrection.LATEST);
  }

}
TOP

Related Classes of com.opengamma.core.security.impl.CoalescingSecuritySourceTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.