Package com.opengamma.engine.view.client

Source Code of com.opengamma.engine.view.client.ViewClientTest

/**
* Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.engine.view.client;

import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertTrue;

import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.testng.annotations.Test;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.opengamma.engine.ComputationTarget;
import com.opengamma.engine.ComputationTargetSpecification;
import com.opengamma.engine.function.FunctionExecutionContext;
import com.opengamma.engine.function.FunctionInputs;
import com.opengamma.engine.function.InMemoryFunctionRepository;
import com.opengamma.engine.marketdata.InMemoryLKVMarketDataProvider;
import com.opengamma.engine.marketdata.InMemoryLKVMarketDataSnapshot;
import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityFilter;
import com.opengamma.engine.marketdata.availability.MarketDataAvailabilityProvider;
import com.opengamma.engine.marketdata.spec.MarketData;
import com.opengamma.engine.marketdata.spec.MarketDataSpecification;
import com.opengamma.engine.target.ComputationTargetType;
import com.opengamma.engine.test.MockFunction;
import com.opengamma.engine.test.TestViewResultListener;
import com.opengamma.engine.test.ViewProcessorTestEnvironment;
import com.opengamma.engine.value.ComputedValue;
import com.opengamma.engine.value.ComputedValueResult;
import com.opengamma.engine.value.ValueProperties;
import com.opengamma.engine.value.ValuePropertyNames;
import com.opengamma.engine.value.ValueRequirement;
import com.opengamma.engine.value.ValueSpecification;
import com.opengamma.engine.view.AggregatedExecutionLog;
import com.opengamma.engine.view.ExecutionLog;
import com.opengamma.engine.view.ExecutionLogMode;
import com.opengamma.engine.view.ExecutionLogWithContext;
import com.opengamma.engine.view.ViewCalculationConfiguration;
import com.opengamma.engine.view.ViewCalculationResultModel;
import com.opengamma.engine.view.ViewComputationResultModel;
import com.opengamma.engine.view.ViewDefinition;
import com.opengamma.engine.view.ViewDeltaResultModel;
import com.opengamma.engine.view.ViewProcess;
import com.opengamma.engine.view.ViewProcessState;
import com.opengamma.engine.view.ViewResultModel;
import com.opengamma.engine.view.execution.ExecutionFlags;
import com.opengamma.engine.view.execution.ExecutionOptions;
import com.opengamma.engine.view.impl.ViewProcessImpl;
import com.opengamma.engine.view.impl.ViewProcessorImpl;
import com.opengamma.engine.view.listener.CycleStartedCall;
import com.opengamma.engine.view.worker.ViewProcessWorker;
import com.opengamma.id.UniqueId;
import com.opengamma.livedata.UserPrincipal;
import com.opengamma.util.log.LogBridge;
import com.opengamma.util.log.LogEvent;
import com.opengamma.util.log.LogLevel;
import com.opengamma.util.log.SimpleLogEvent;
import com.opengamma.util.money.Currency;
import com.opengamma.util.test.TestGroup;
import com.opengamma.util.test.Timeout;
import com.opengamma.util.tuple.Pair;

/**
* Tests ViewClient
*/
@Test(groups = TestGroup.INTEGRATION)
public class ViewClientTest {

  private static final long TIMEOUT = Timeout.standardTimeoutMillis();

  @Test
  public void testSingleViewMultipleClients() {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    env.init();
    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client1 = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    assertNotNull(client1.getUniqueId());

    client1.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));
    final ViewProcessImpl client1Process = env.getViewProcess(vp, client1.getUniqueId());
    assertTrue(client1Process.getState() == ViewProcessState.RUNNING);

    final ViewClient client2 = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    assertNotNull(client2.getUniqueId());
    assertFalse(client1.getUniqueId().equals(client2.getUniqueId()));

    client2.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));
    final ViewProcessImpl client2Process = env.getViewProcess(vp, client2.getUniqueId());
    assertEquals(client1Process, client2Process);
    assertTrue(client2Process.getState() == ViewProcessState.RUNNING);

    client1.detachFromViewProcess();
    assertTrue(client2Process.getState() == ViewProcessState.RUNNING);

    client2.detachFromViewProcess();
    assertTrue(client2Process.getState() == ViewProcessState.TERMINATED);

    client1.shutdown();
    client2.shutdown();
  }

  @Test
  public void testCascadingShutdown() {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    env.init();
    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client1 = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client1.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    final ViewClient client2 = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client2.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    final ViewProcessImpl view = env.getViewProcess(vp, client1.getUniqueId());

    vp.stop();

    assertFalse(vp.isRunning());
    assertFalse(view.isRunning());
    assertTrue(view.getState() == ViewProcessState.TERMINATED);

    assertFalse(client1.isAttached());
    assertFalse(client2.isAttached());

    client1.shutdown();
    client2.shutdown();
  }

  @Test
  public void testComputationResultsFlow() throws InterruptedException {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    final SynchronousInMemoryLKVSnapshotProvider marketDataProvider = new SynchronousInMemoryLKVSnapshotProvider();
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 0);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 0);
    env.setMarketDataProvider(marketDataProvider);
    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client.setFragmentResultMode(ViewResultMode.FULL_ONLY);
    final TestViewResultListener resultListener = new TestViewResultListener();
    client.setResultListener(resultListener);

    // Client not attached - should not have been listening to anything that might have been going on
    assertEquals(0, resultListener.getQueueSize());

    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 1);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 2);

    assertEquals(0, resultListener.getQueueSize());

    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    final ViewProcessImpl viewProcess = env.getViewProcess(vp, client.getUniqueId());
    assertTrue(viewProcess.getState() == ViewProcessState.RUNNING);

    resultListener.assertViewDefinitionCompiled(TIMEOUT);
    resultListener.assertCycleStarted(TIMEOUT);
    final ViewResultModel result1Fragment = resultListener.getCycleFragmentCompleted(TIMEOUT).getFullFragment();
    assertNotNull(result1Fragment);
    final ViewComputationResultModel result1 = resultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertNotNull(result1);

    Map<ValueRequirement, Object> expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 1);
    expected.put(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 2);
    assertComputationResult(expected, env.getCalculationResult(result1));
    assertComputationResult(expected, env.getCalculationResult(result1Fragment));
    assertTrue(client.isResultAvailable());
    assertEquals(result1, client.getLatestResult());

    client.pause();

    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 3);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 4);

    env.getCurrentWorker(viewProcess).requestCycle();

    // Should have been merging results received in the meantime
    client.resume();
    final UniqueId cycleStartedId = resultListener.getCycleStarted(TIMEOUT).getCycleMetadata().getViewCycleId();
    resultListener.assertCycleFragmentCompleted(TIMEOUT);
    final ViewComputationResultModel result2 = resultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertEquals(result2.getViewCycleId(), cycleStartedId);

    expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 3);
    expected.put(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 4);
    assertComputationResult(expected, env.getCalculationResult(result2));
  }

  @Test
  public void testDeltaResults() throws InterruptedException {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    final SynchronousInMemoryLKVSnapshotProvider marketDataProvider = new SynchronousInMemoryLKVSnapshotProvider();
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 0);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), 0);
    env.setMarketDataProvider(marketDataProvider);
    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client.setResultMode(ViewResultMode.DELTA_ONLY);
    client.setFragmentResultMode(ViewResultMode.FULL_ONLY);

    final TestViewResultListener resultListener = new TestViewResultListener();
    client.setResultListener(resultListener);

    // Client not attached - should not have been listening to anything that might have been going on
    assertEquals(0, resultListener.getQueueSize());

    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 1);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), 2);

    assertEquals(0, resultListener.getQueueSize());

    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));
    resultListener.assertViewDefinitionCompiled(TIMEOUT);
    resultListener.assertCycleStarted(TIMEOUT);
    resultListener.assertCycleFragmentCompleted(TIMEOUT);
    final ViewDeltaResultModel result1 = resultListener.getCycleCompleted(TIMEOUT).getDeltaResult();
    assertNotNull(result1);

    Map<ValueRequirement, Object> expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), 1);
    expected.put(ViewProcessorTestEnvironment.getPrimitive2(), 2);
    assertComputationResult(expected, env.getCalculationResult(result1));

    client.pause();

    // Just update one live data value, and only this one value should end up in the delta
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 3);

    assertEquals(0, resultListener.getQueueSize());
    final ViewProcessImpl viewProcess = env.getViewProcess(vp, client.getUniqueId());
    env.getCurrentWorker(viewProcess).requestCycle();

    // Should have been merging results received in the meantime
    resultListener.assertNoCalls(TIMEOUT);
    client.resume();
    resultListener.assertCycleStarted(TIMEOUT);
    resultListener.assertCycleFragmentCompleted(TIMEOUT);
    final ViewDeltaResultModel result2 = resultListener.getCycleCompleted(TIMEOUT).getDeltaResult();

    expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), 3);
    assertComputationResult(expected, env.getCalculationResult(result2));
  }

  @Test
  public void testStates() throws InterruptedException {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    final SynchronousInMemoryLKVSnapshotProvider marketDataProvider = new SynchronousInMemoryLKVSnapshotProvider();
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 0);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 0);
    env.setMarketDataProvider(marketDataProvider);
    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client1 = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client1.setFragmentResultMode(ViewResultMode.FULL_ONLY);
    final TestViewResultListener client1ResultListener = new TestViewResultListener();
    client1.setResultListener(client1ResultListener);

    assertEquals(0, client1ResultListener.getQueueSize());

    client1.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    // Wait for first computation cycle
    client1ResultListener.assertViewDefinitionCompiled(TIMEOUT);
    client1ResultListener.expectNextCall(CycleStartedCall.class, TIMEOUT);
    client1ResultListener.assertCycleFragmentCompleted(TIMEOUT);
    client1ResultListener.assertCycleCompleted(TIMEOUT);

    final ViewClient client2 = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client2.setFragmentResultMode(ViewResultMode.FULL_ONLY);
    final TestViewResultListener client2ResultListener = new TestViewResultListener();
    client2.setResultListener(client2ResultListener);

    assertEquals(0, client2ResultListener.getQueueSize());
    client2.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    // Initial result should be pushed through
    client2ResultListener.assertViewDefinitionCompiled(TIMEOUT);
    client2ResultListener.assertCycleCompleted(TIMEOUT);

    final ViewProcessImpl viewProcess1 = env.getViewProcess(vp, client1.getUniqueId());
    final ViewProcessImpl viewProcess2 = env.getViewProcess(vp, client2.getUniqueId());
    assertEquals(viewProcess1, viewProcess2);

    client1.pause();
    client1ResultListener.assertNoCalls(TIMEOUT);

    // Now client 1 is paused, so any changes should be batched.
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 1);
    env.getCurrentWorker(viewProcess1).requestCycle();
    client2ResultListener.assertCycleStarted(TIMEOUT);
    client2ResultListener.assertCycleFragmentCompleted(TIMEOUT);
    client2ResultListener.assertCycleCompleted(TIMEOUT);
    assertEquals(0, client2ResultListener.getQueueSize());
    client1ResultListener.assertNoCalls(TIMEOUT);

    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 2);
    env.getCurrentWorker(viewProcess1).requestCycle();
    client2ResultListener.assertCycleStarted(TIMEOUT);
    client2ResultListener.assertCycleFragmentCompleted(TIMEOUT);
    client2ResultListener.assertCycleCompleted(TIMEOUT);
    assertEquals(0, client2ResultListener.getQueueSize());
    client1ResultListener.assertNoCalls(TIMEOUT);

    // Resuming should release the most recent result to the client
    client1.resume();
    client1ResultListener.getCycleStarted(TIMEOUT).getCycleMetadata();
    final ViewComputationResultModel result2Fragment = client1ResultListener.getCycleFragmentCompleted(TIMEOUT).getFullFragment();
    final ViewComputationResultModel result2 = client1ResultListener.getCycleCompleted(TIMEOUT).getFullResult();
    Map<ValueRequirement, Object> expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 2);
    expected.put(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 0);
    assertComputationResult(expected, env.getCalculationResult(result2Fragment));
    assertComputationResult(expected, env.getCalculationResult(result2));

    // Changes should now propagate straight away to both listeners
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 3);
    env.getCurrentWorker(viewProcess1).requestCycle();
    client1ResultListener.assertCycleStarted(TIMEOUT);
    client2ResultListener.assertCycleStarted(TIMEOUT);
    client2ResultListener.assertCycleFragmentCompleted(TIMEOUT);
    client2ResultListener.assertCycleCompleted(TIMEOUT);
    final ViewComputationResultModel result3Fragment = client1ResultListener.getCycleFragmentCompleted(TIMEOUT).getFullFragment();
    final ViewComputationResultModel result3 = client1ResultListener.getCycleCompleted(TIMEOUT).getFullResult();
    expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 3);
    expected.put(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 0);
    assertComputationResult(expected, env.getCalculationResult(result3Fragment));
    assertComputationResult(expected, env.getCalculationResult(result3));

    // Pause results again and we should be back to merging both whole cycle results and fragments
    client1.pause();
    client2ResultListener.assertNoCalls(TIMEOUT);
    client1ResultListener.assertNoCalls(TIMEOUT);

    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 1);
    env.getCurrentWorker(viewProcess1).requestCycle();
    client2ResultListener.assertCycleStarted(TIMEOUT);
    client2ResultListener.assertCycleFragmentCompleted(TIMEOUT);
    client2ResultListener.assertCycleCompleted(TIMEOUT);
    assertEquals(0, client2ResultListener.getQueueSize());
    client1ResultListener.assertNoCalls(TIMEOUT);

    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 2);
    env.getCurrentWorker(viewProcess1).requestCycle();
    client2ResultListener.assertCycleStarted(TIMEOUT);
    client2ResultListener.assertCycleFragmentCompleted(TIMEOUT);
    client2ResultListener.assertCycleCompleted(TIMEOUT);
    assertEquals(0, client2ResultListener.getQueueSize());
    client1ResultListener.assertNoCalls(TIMEOUT);

    // Start results again
    client1.resume();
    client1ResultListener.assertCycleStarted(TIMEOUT);
    final ViewComputationResultModel result4Fragment = client1ResultListener.getCycleFragmentCompleted(TIMEOUT).getFullFragment();
    final ViewComputationResultModel result4 = client1ResultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertEquals(0, client1ResultListener.getQueueSize());
    client2ResultListener.assertNoCalls(TIMEOUT);
    expected = new HashMap<ValueRequirement, Object>();
    expected.put(ViewProcessorTestEnvironment.getPrimitive1(), (byte) 3);
    expected.put(ViewProcessorTestEnvironment.getPrimitive2(), (byte) 2);
    assertComputationResult(expected, env.getCalculationResult(result4Fragment));
    assertComputationResult(expected, env.getCalculationResult(result4));

    client1.detachFromViewProcess();
    client2ResultListener.assertNoCalls(TIMEOUT);
    client1ResultListener.assertNoCalls(TIMEOUT);

    client1.shutdown();
    client1ResultListener.assertClientShutdown(TIMEOUT);

    client2.setResultListener(null);
    client2.shutdown();
    client2ResultListener.assertNoCalls(TIMEOUT);
  }

  @Test(expectedExceptions = IllegalStateException.class)
  public void testUseTerminatedClient() {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    final ViewProcess viewProcess = env.getViewProcess(vp, client.getUniqueId());

    client.shutdown();

    assertEquals(ViewProcessState.TERMINATED, viewProcess.getState());

    client.pause();
  }

  @Test
  public void testChangeOfListeners() throws InterruptedException {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    final SynchronousInMemoryLKVSnapshotProvider marketDataProvider = new SynchronousInMemoryLKVSnapshotProvider();
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 0);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), 0);
    env.setMarketDataProvider(marketDataProvider);
    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    client.setFragmentResultMode(ViewResultMode.FULL_ONLY);
    final TestViewResultListener resultListener1 = new TestViewResultListener();
    client.setResultListener(resultListener1);

    // Start live computation and collect the initial result
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 2);

    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));
    final ViewProcessImpl viewProcess = env.getViewProcess(vp, client.getUniqueId());
    assertEquals(ViewProcessState.RUNNING, viewProcess.getState());

    final ViewProcessWorker worker = env.getCurrentWorker(viewProcess);
    resultListener1.assertViewDefinitionCompiled(TIMEOUT);
    resultListener1.assertCycleStarted(TIMEOUT);
    resultListener1.assertCycleFragmentCompleted(TIMEOUT);
    resultListener1.assertCycleCompleted(TIMEOUT);
    assertEquals(0, resultListener1.getQueueSize());

    // Push through a second result
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 3);
    worker.requestCycle();
    resultListener1.assertCycleStarted(TIMEOUT);
    resultListener1.assertCycleFragmentCompleted(TIMEOUT);
    resultListener1.assertCycleCompleted(TIMEOUT);
    assertEquals(0, resultListener1.getQueueSize());

    // Change listener
    final TestViewResultListener resultListener2 = new TestViewResultListener();
    client.setResultListener(resultListener2);

    // Push through a result which should arrive at the new listener
    worker.requestCycle();
    resultListener2.assertCycleStarted(TIMEOUT);
    resultListener2.assertCycleFragmentCompleted(TIMEOUT);
    resultListener2.assertCycleCompleted(TIMEOUT);
    assertEquals(0, resultListener1.getQueueSize());
    assertEquals(0, resultListener2.getQueueSize());

    client.setResultListener(null);
    client.shutdown();
    assertEquals(ViewProcessState.TERMINATED, viewProcess.getState());

    vp.stop();
  }

  @Test
  public void testOldRecalculationThreadDies() throws InterruptedException {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    final SynchronousInMemoryLKVSnapshotProvider marketDataProvider = new SynchronousInMemoryLKVSnapshotProvider();
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 0);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), 0);
    env.setMarketDataProvider(marketDataProvider);
    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);

    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));
    final ViewProcessImpl viewProcess1 = env.getViewProcess(vp, client.getUniqueId());

    final ViewProcessWorker worker1 = env.getCurrentWorker(viewProcess1);
    assertFalse(worker1.isTerminated());

    client.detachFromViewProcess();
    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));
    final ViewProcessImpl viewProcess2 = env.getViewProcess(vp, client.getUniqueId());
    final ViewProcessWorker worker2 = env.getCurrentWorker(viewProcess2);

    assertFalse(viewProcess1 == viewProcess2);
    assertTrue(worker1.join(TIMEOUT));

    vp.stop();

    assertTrue(worker2.join(TIMEOUT));
  }

  //-------------------------------------------------------------------------
  @Test
  public void testSetMinimumLogMode() throws InterruptedException {
    final ViewProcessorTestEnvironment env = new ViewProcessorTestEnvironment();
    final SynchronousInMemoryLKVSnapshotProvider marketDataProvider = new SynchronousInMemoryLKVSnapshotProvider();
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive1(), 0);
    marketDataProvider.addValue(ViewProcessorTestEnvironment.getPrimitive2(), 0);
    env.setMarketDataProvider(marketDataProvider);
    final InMemoryFunctionRepository functionRepository = new InMemoryFunctionRepository();

    final ComputationTarget target = new ComputationTarget(ComputationTargetType.CURRENCY, Currency.USD);
    final MockFunction fn1 = new MockFunction(MockFunction.UNIQUE_ID + "1", target) {

      @Override
      public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
        LogBridge.getInstance().log(new SimpleLogEvent(LogLevel.WARN, "Warning during execution"));
        LogBridge.getInstance().log(new SimpleLogEvent(LogLevel.ERROR, "Error during execution"));
        return super.execute(executionContext, inputs, target, desiredValues);
      }

    };
    final ValueRequirement requirement1 = new ValueRequirement("value1", target.toSpecification());
    fn1.addResult(new ValueSpecification(requirement1.getValueName(), target.toSpecification(), ValueProperties.with(ValuePropertyNames.FUNCTION, "fn1").get()), "result1");
    functionRepository.addFunction(fn1);

    final MockFunction fn2 = new MockFunction(MockFunction.UNIQUE_ID + "2", target) {

      @Override
      public Set<ComputedValue> execute(final FunctionExecutionContext executionContext, final FunctionInputs inputs, final ComputationTarget target, final Set<ValueRequirement> desiredValues) {
        LogBridge.getInstance().log(new SimpleLogEvent(LogLevel.WARN, "Warning during execution"));
        return super.execute(executionContext, inputs, target, desiredValues);
      }

    };
    fn2.addRequirement(requirement1);
    final ValueRequirement requirement2 = new ValueRequirement("value2", target.toSpecification());
    fn2.addResult(new ValueSpecification(requirement2.getValueName(), target.toSpecification(), ValueProperties.with(ValuePropertyNames.FUNCTION, "fn2").get()), "result2");
    functionRepository.addFunction(fn2);

    env.setFunctionRepository(functionRepository);

    final ViewDefinition vd = new ViewDefinition(UniqueId.of("test", "vd1"), "Test view", UserPrincipal.getLocalUser());
    final ViewCalculationConfiguration calcConfig = new ViewCalculationConfiguration(vd, "Default");
    calcConfig.addSpecificRequirement(requirement2);
    vd.addViewCalculationConfiguration(calcConfig);
    vd.setMinFullCalculationPeriod(Long.MAX_VALUE); // Never force a full calculation
    vd.setMaxFullCalculationPeriod(Long.MAX_VALUE); // Never force a full calculation
    env.setViewDefinition(vd);

    env.init();

    final ViewProcessorImpl vp = env.getViewProcessor();
    vp.start();

    final ViewClient client = vp.createViewClient(ViewProcessorTestEnvironment.TEST_USER);
    final TestViewResultListener resultListener = new TestViewResultListener();
    client.setResultListener(resultListener);

    client.attachToViewProcess(env.getViewDefinition().getUniqueId(), ExecutionOptions.infinite(MarketData.live(), ExecutionFlags.none().get()));

    resultListener.assertViewDefinitionCompiled(TIMEOUT);
    final ViewComputationResultModel result1 = resultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertEquals(0, resultListener.getQueueSize());

    assertEquals(1, result1.getAllResults().size());
    final ComputedValueResult result1Value = Iterables.getOnlyElement(result1.getAllResults()).getComputedValue();
    assertEquals("result2", result1Value.getValue());

    final AggregatedExecutionLog log1 = result1Value.getAggregatedExecutionLog();
    assertNotNull(log1);
    assertTrue(log1.getLogLevels().contains(LogLevel.ERROR));
    assertTrue(log1.getLogLevels().contains(LogLevel.WARN));
    assertFalse(log1.getLogLevels().contains(LogLevel.INFO));
    assertNull(log1.getLogs());

    final Pair<String, ValueSpecification> resultSpec = Pair.of(calcConfig.getName(), Iterables.getOnlyElement(client.getLatestCompiledViewDefinition().getTerminalValuesRequirements().keySet()));
    client.setMinimumLogMode(ExecutionLogMode.FULL, ImmutableSet.of(resultSpec));

    final ViewProcessImpl viewProcess = env.getViewProcess(vp, client.getUniqueId());
    final ViewProcessWorker worker = env.getCurrentWorker(viewProcess);
    worker.triggerCycle();

    final ViewComputationResultModel result2 = resultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertEquals(0, resultListener.getQueueSize());

    assertEquals(1, result2.getAllResults().size());
    final ComputedValueResult result2Value = Iterables.getOnlyElement(result2.getAllResults()).getComputedValue();
    assertEquals("result2", result2Value.getValue());

    final AggregatedExecutionLog log2 = result2Value.getAggregatedExecutionLog();
    assertNotNull(log2);
    assertTrue(log2.getLogLevels().contains(LogLevel.ERROR));
    assertTrue(log2.getLogLevels().contains(LogLevel.WARN));
    assertFalse(log2.getLogLevels().contains(LogLevel.INFO));
    assertNotNull(log2.getLogs());
    assertEquals(2, log2.getLogs().size());

    final ExecutionLogWithContext result2LogContext = log2.getLogs().get(0);
    assertNotNull(result2LogContext);
    assertEquals(fn2.getFunctionDefinition().getShortName(), result2LogContext.getFunctionName());
    assertEquals(resultSpec.getSecond().getTargetSpecification(), result2LogContext.getTargetSpecification());
    final ExecutionLog result2Log = result2LogContext.getExecutionLog();
    assertEquals(1, result2Log.getEvents().size());
    final LogEvent result2Event1 = result2Log.getEvents().get(0);
    assertEquals(LogLevel.WARN, result2Event1.getLevel());
    assertEquals("Warning during execution", result2Event1.getMessage());
    assertNull(result2Log.getExceptionClass());
    assertNull(result2Log.getExceptionMessage());
    assertNull(result2Log.getExceptionStackTrace());

    final ExecutionLogWithContext result1LogContext = log2.getLogs().get(1);
    assertNotNull(result1LogContext);
    assertEquals(fn1.getFunctionDefinition().getShortName(), result1LogContext.getFunctionName());
    assertEquals(resultSpec.getSecond().getTargetSpecification(), result1LogContext.getTargetSpecification());
    final ExecutionLog result1Log = result1LogContext.getExecutionLog();
    assertEquals(2, result1Log.getEvents().size());
    final LogEvent result1Event1 = result1Log.getEvents().get(0);
    assertEquals(LogLevel.WARN, result1Event1.getLevel());
    assertEquals("Warning during execution", result1Event1.getMessage());
    final LogEvent result1Event2 = result1Log.getEvents().get(1);
    assertEquals(LogLevel.ERROR, result1Event2.getLevel());
    assertEquals("Error during execution", result1Event2.getMessage());
    assertNull(result1Log.getExceptionClass());
    assertNull(result1Log.getExceptionMessage());
    assertNull(result1Log.getExceptionStackTrace());

    client.setMinimumLogMode(ExecutionLogMode.INDICATORS, ImmutableSet.of(resultSpec));
    worker.triggerCycle();

    final ViewComputationResultModel result3 = resultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertEquals(0, resultListener.getQueueSize());

    assertEquals(1, result3.getAllResults().size());
    final ComputedValueResult result3Value = Iterables.getOnlyElement(result3.getAllResults()).getComputedValue();
    assertEquals("result2", result3Value.getValue());

    final AggregatedExecutionLog log3 = result3Value.getAggregatedExecutionLog();
    assertNotNull(log3);
    // Delta cycle - should reuse the previous result which *does* include logs.
    assertNotNull(log3.getLogs());

    // Force a full cycle - should *not* reuse any previous result, so back to indicators only
    // TODO: [PLAT-3215] This is bad; future optimizations will not necessarily mean a full cycle happens just because a new view definition got posted
    vd.setUniqueId(UniqueId.of(vd.getUniqueId().getScheme(), vd.getUniqueId().getValue(), "PLAT-3215"));
    worker.updateViewDefinition(vd);
    worker.triggerCycle();

    resultListener.assertViewDefinitionCompiled(TIMEOUT);
    final ViewComputationResultModel result4 = resultListener.getCycleCompleted(TIMEOUT).getFullResult();
    assertEquals(0, resultListener.getQueueSize());

    assertEquals(1, result4.getAllResults().size());
    final ComputedValueResult result4Value = Iterables.getOnlyElement(result4.getAllResults()).getComputedValue();
    assertEquals("result2", result4Value.getValue());

    final AggregatedExecutionLog log4 = result4Value.getAggregatedExecutionLog();
    assertNotNull(log4);
    assertNull(log4.getLogs());
  }

  //-------------------------------------------------------------------------
  private void assertComputationResult(final Map<ValueRequirement, Object> expected, final ViewCalculationResultModel result) {
    assertNotNull(result);
    final Set<ValueRequirement> remaining = new HashSet<ValueRequirement>(expected.keySet());
    final Collection<ComputationTargetSpecification> targets = result.getAllTargets();
    for (final ComputationTargetSpecification target : targets) {
      final Map<Pair<String, ValueProperties>, ComputedValueResult> values = result.getValues(target);
      for (final Map.Entry<Pair<String, ValueProperties>, ComputedValueResult> value : values.entrySet()) {
        final String valueName = value.getKey().getFirst();
        final ValueRequirement requirement = new ValueRequirement(valueName, target.getType(), target.getUniqueId());
        assertTrue(expected.containsKey(requirement));

        assertEquals(expected.get(requirement), value.getValue().getValue());
        remaining.remove(requirement);
      }
    }
    assertEquals(Collections.emptySet(), remaining);
  }

  /**
   * Avoids the ConcurrentHashMap-based implementation of InMemoryLKVSnapshotProvider, where the LKV map can appear to lag behind if accessed from a different thread immediately after a change.
   */
  private static class SynchronousInMemoryLKVSnapshotProvider extends InMemoryLKVMarketDataProvider {

    @Override
    public synchronized InMemoryLKVMarketDataSnapshot snapshot(final MarketDataSpecification marketDataSpec) {
      return super.snapshot(marketDataSpec);
    }

    @Override
    public synchronized void addValue(final ValueSpecification valueSpecification, final Object value) {
      super.addValue(valueSpecification, value);
    }

    @Override
    public synchronized void removeValue(final ValueSpecification valueSpecification) {
      super.removeValue(valueSpecification);
    }

    @Override
    public MarketDataAvailabilityProvider getAvailabilityProvider(final MarketDataSpecification marketDataSpec) {
      final MarketDataAvailabilityProvider underlying = super.getAvailabilityProvider(marketDataSpec);
      return new MarketDataAvailabilityProvider() {

        @Override
        public ValueSpecification getAvailability(final ComputationTargetSpecification targetSpec, final Object target, final ValueRequirement desiredValue) {
          synchronized (SynchronousInMemoryLKVSnapshotProvider.this) {
            return underlying.getAvailability(targetSpec, target, desiredValue);
          }
        }

        @Override
        public MarketDataAvailabilityFilter getAvailabilityFilter() {
          throw new UnsupportedOperationException();
        }

        @Override
        public Serializable getAvailabilityHintKey() {
          return underlying.getAvailabilityHintKey();
        }

      };
    }

  }

}
TOP

Related Classes of com.opengamma.engine.view.client.ViewClientTest

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.