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

us.ihmc.simulationconstructionset.util.simulationRunner.SimulationRewindabilityVerifierWithStackTracing Maven / Gradle / Ivy

There is a newer version: 0.25.2
Show newest version
package us.ihmc.simulationconstructionset.util.simulationRunner;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;

import us.ihmc.simulationconstructionset.SimulationConstructionSet;
import us.ihmc.yoVariables.listener.YoVariableChangedListener;
import us.ihmc.yoVariables.registry.YoRegistry;
import us.ihmc.yoVariables.variable.YoVariable;

public class SimulationRewindabilityVerifierWithStackTracing
{
   private final double EPSILON = 1e-14;

   private final VariablesThatShouldMatchList VariablesThatShouldMatchList;
   private final YoRegistry rootRegistryOne, rootRegistryTwo;
   private final LinkedHashMap> changesForSimOne = new LinkedHashMap<>();
   private final LinkedHashMap> changesForSimTwo = new LinkedHashMap<>();

   private boolean recordDifferencesForSimOne = false;
   private boolean recordDifferencesForSimTwo = false;

   public SimulationRewindabilityVerifierWithStackTracing(SimulationConstructionSet simulationOne, SimulationConstructionSet simulationTwo,
                                                          ArrayList exceptions)
   {
      rootRegistryOne = simulationOne.getRootRegistry();
      rootRegistryTwo = simulationTwo.getRootRegistry();
      VariablesThatShouldMatchList = new VariablesThatShouldMatchList(rootRegistryOne, rootRegistryTwo, exceptions);

      YoVariableChangedListener variableChangedListenerForSimOne = new YoVariableChangedListener()
      {
         @Override
         public void changed(YoVariable variableInRegistryOne)
         {
            if (!recordDifferencesForSimOne)
               return;

            YoVariable variableInRegistryTwo = VariablesThatShouldMatchList.getYoVariableInListTwo(variableInRegistryOne.getFullNameString());
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

            Thread thread = Thread.currentThread();
            VariableChangeAndStackTrace change = new VariableChangeAndStackTrace(thread,
                                                                                 variableInRegistryOne,
                                                                                 variableInRegistryTwo,
                                                                                 variableInRegistryOne.getValueAsDouble(),
                                                                                 stackTrace);

            ArrayList changesForThread = changesForSimOne.get(thread);
            if (changesForThread == null)
            {
               changesForThread = new ArrayList<>();
               changesForSimOne.put(thread, changesForThread);
            }
            changesForThread.add(change);
         }
      };

      YoVariableChangedListener variableChangedListenerForSimTwo = new YoVariableChangedListener()
      {
         @Override
         public void changed(YoVariable variableInRegistryTwo)
         {
            if (!recordDifferencesForSimTwo)
               return;

            YoVariable variableInRegistryOne = VariablesThatShouldMatchList.getYoVariableInListOne(variableInRegistryTwo.getFullNameString());
            StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

            Thread thread = Thread.currentThread();
            VariableChangeAndStackTrace change = new VariableChangeAndStackTrace(thread,
                                                                                 variableInRegistryOne,
                                                                                 variableInRegistryTwo,
                                                                                 variableInRegistryTwo.getValueAsDouble(),
                                                                                 stackTrace);

            ArrayList changesForThread = changesForSimTwo.get(thread);
            if (changesForThread == null)
            {
               changesForThread = new ArrayList<>();
               changesForSimTwo.put(thread, changesForThread);
            }
            changesForThread.add(change);
         }
      };

      List variablesThatShouldMatch = VariablesThatShouldMatchList.getVariablesThatShouldMatch();
      for (YoVariable[] variablesToMatch : variablesThatShouldMatch)
      {
         variablesToMatch[0].addListener(variableChangedListenerForSimOne);
         variablesToMatch[1].addListener(variableChangedListenerForSimTwo);
      }
   }

   public void clearChangesForSimulations()
   {
      changesForSimOne.clear();
      changesForSimTwo.clear();
   }

   public void setRecordDifferencesForSimOne(boolean recordDifferencesForSimOne)
   {
      this.recordDifferencesForSimOne = recordDifferencesForSimOne;
   }

   public void setRecordDifferencesForSimTwo(boolean recordDifferencesForSimTwo)
   {
      this.recordDifferencesForSimTwo = recordDifferencesForSimTwo;
   }

   public LinkedHashMap> getVariableChangesAndStackTracesForSimulationOne()
   {
      return changesForSimOne;
   }

   public LinkedHashMap> getVariableChangesAndStackTracesForSimulationTwo()
   {
      return changesForSimTwo;
   }

   public boolean areTheVariableChangesDifferent()
   {
      ArrayList threadNames = getThreadNames();
      for (String threadName : threadNames)
      {
         //         System.out.println("threadName = " + threadName);
         if (areTheVariableChangesDifferent(threadName))
            return true;
      }

      return false;
   }

   public boolean areTheVariableChangesDifferent(String threadName)
   {
      Thread threadOne = getThreadWithName(threadName, changesForSimOne);
      Thread threadTwo = getThreadWithName(threadName, changesForSimTwo);

      ArrayList changesForSimOne = this.changesForSimOne.get(threadOne);
      ArrayList changesForSimTwo = this.changesForSimTwo.get(threadTwo);

      int sizeOne = changesForSimOne.size();
      int sizeTwo = changesForSimTwo.size();

      if (sizeOne != sizeTwo)
         return true;

      for (int i = 0; i < sizeOne; i++)
      {
         VariableChangeAndStackTrace changeOne = changesForSimOne.get(i);
         VariableChangeAndStackTrace changeTwo = changesForSimTwo.get(i);

         boolean variablesAreDifferent = !changeOne.variableOne.getName().equals(changeTwo.variableTwo.getName());
         boolean finalValueIsDifferent = Math.abs(changeOne.variableOne.getValueAsDouble() - changeOne.variableTwo.getValueAsDouble()) > EPSILON;
         boolean localChangeValuesAreDifferent = Math.abs(changeOne.variableValue - changeTwo.variableValue) > EPSILON;

         if (variablesAreDifferent || finalValueIsDifferent || localChangeValuesAreDifferent)
            return true;
      }

      return false;
   }

   private Thread getThreadWithName(String name, LinkedHashMap> changes)
   {
      Set keySet = changes.keySet();

      for (Thread thread : keySet)
      {
         if (thread.getName().equals(name))
            return thread;
      }

      return null;
   }

   private ArrayList getThreadNames()
   {
      ArrayList threadNamesToReturn = new ArrayList<>();

      Set threadsForSimOne = changesForSimOne.keySet();

      for (Thread thread : threadsForSimOne)
      {
         threadNamesToReturn.add(thread.getName());
      }

      Set threadsForSimTwo = changesForSimTwo.keySet();
      for (Thread thread : threadsForSimTwo)
      {
         if (!threadNamesToReturn.contains(thread.getName()))
         {
            throw new RuntimeException("Thread named" + thread.getName() + " is in second sim but not in first!");
         }
      }

      return threadNamesToReturn;
   }

   public int countNumberOfThreadsThatChangeTheVariables(ArrayList changes)
   {
      HashSet threads = new HashSet<>();

      for (int i = 0; i < changes.size(); i++)
      {
         VariableChangeAndStackTrace change = changes.get(i);

         Thread thread = change.thread;
         threads.add(thread);
      }

      return threads.size();
   }

   public int findIndexOfFistVariableChange(String threadName)
   {
      Thread threadOne = getThreadWithName(threadName, changesForSimOne);
      Thread threadTwo = getThreadWithName(threadName, changesForSimTwo);

      ArrayList changesForSimOne = this.changesForSimOne.get(threadOne);
      ArrayList changesForSimTwo = this.changesForSimTwo.get(threadTwo);

      int sizeOne = changesForSimOne.size();
      int sizeTwo = changesForSimTwo.size();

      int minSize = Math.min(sizeOne, sizeTwo);

      for (int index = 0; index < minSize; index++)
      {
         VariableChangeAndStackTrace changeOne = changesForSimOne.get(index);
         VariableChangeAndStackTrace changeTwo = changesForSimTwo.get(index);

         boolean variablesAreDifferent = !(changeOne.variableOne.getName().equals(changeTwo.variableTwo.getName()));
         boolean localChangeValuesAreDifferent = Math.abs(changeOne.variableValue - changeTwo.variableValue) > EPSILON;

         if (variablesAreDifferent || localChangeValuesAreDifferent)
            return index;
      }

      return -1;
   }

   public void printOutStackTracesOfFirstChangedVariable()
   {
      ArrayList threadNames = getThreadNames();

      for (String threadName : threadNames)
      {
         System.out.println("\n\nThread = " + threadName);
         printOutStackTracesOfFirstChangedVariable(threadName);
      }
   }

   public void printOutStackTracesOfFirstChangedVariable(String threadName)
   {
      Thread threadOne = getThreadWithName(threadName, changesForSimOne);
      Thread threadTwo = getThreadWithName(threadName, changesForSimTwo);

      ArrayList changesForSimOne = this.changesForSimOne.get(threadOne);
      ArrayList changesForSimTwo = this.changesForSimTwo.get(threadTwo);

      int firstChangedIndex = findIndexOfFistVariableChange(threadName);
      if (firstChangedIndex < 0)
         return;
      System.out.println("\nFirst change index at : " + firstChangedIndex);

      System.out.println("\n Local changes for change one:");
      printLocalChangesBeforeAndAfterIndex(changesForSimOne, firstChangedIndex);
      System.out.println("\n Local changes for change two:");
      printLocalChangesBeforeAndAfterIndex(changesForSimTwo, firstChangedIndex);

      System.out.println("\n Stack traces for change one:");
      printStackTraceBeforeAndAfterIndex(changesForSimOne, firstChangedIndex);
      System.out.println("\n Stack traces for change two:");
      printStackTraceBeforeAndAfterIndex(changesForSimTwo, firstChangedIndex);
   }

   private static void printLocalChangesBeforeAndAfterIndex(ArrayList changesForSim, int firstChangedIndex)
   {
      int sizeOne = changesForSim.size();

      int numberBefore = 2;
      int numberAfter = 2;

      int startIndex = Math.max(0, firstChangedIndex - numberBefore);
      int endIndex = Math.min(sizeOne - 1, firstChangedIndex + numberAfter);

      for (int i = startIndex; i <= endIndex; i++)
      {
         VariableChangeAndStackTrace change = changesForSim.get(i);
         String highlight = "";
         if (i == firstChangedIndex)
            highlight = "*** ";
         System.out.println(highlight + "Changed variable = " + change.variableOne.getName() + " = " + change.variableValue + ", other = "
               + change.variableTwo.getName());
      }
   }

   private static void printStackTraceBeforeAndAfterIndex(ArrayList changesForSim, int firstChangedIndex)
   {
      int sizeOne = changesForSim.size();

      int numberBefore = 0;
      int numberAfter = 0;

      int startIndex = Math.max(0, firstChangedIndex - numberBefore);
      int endIndex = Math.min(sizeOne - 1, firstChangedIndex + numberAfter);

      for (int i = startIndex; i <= endIndex; i++)
      {
         VariableChangeAndStackTrace change = changesForSim.get(i);
         System.out.println("Changed variable = " + change.variableOne.getName() + " = " + change.variableValue + ", other = " + change.variableTwo.getName());
         printStackTrace(change.stackTrace);
      }
   }

   public void printOutVariableChangesStartingAtIndex(String threadName, int index)
   {
      Thread threadOne = getThreadWithName(threadName, changesForSimOne);
      Thread threadTwo = getThreadWithName(threadName, changesForSimTwo);

      ArrayList changesForSimOne = this.changesForSimOne.get(threadOne);
      ArrayList changesForSimTwo = this.changesForSimTwo.get(threadTwo);

      int sizeOne = changesForSimOne.size();
      int sizeTwo = changesForSimTwo.size();

      int minSize = Math.min(sizeOne, sizeTwo);

      for (int i = 0; i < minSize; i++)
      {
         VariableChangeAndStackTrace changeOne = changesForSimOne.get(i);
         VariableChangeAndStackTrace changeTwo = changesForSimTwo.get(i);

         System.out.println("Changed variable = " + changeOne.variableOne.getName() + " = " + changeOne.variableValue + ", other = "
               + changeTwo.variableTwo.getName() + " = " + changeTwo.variableValue);
      }
   }

   private static void printStackTrace(StackTraceElement[] stackTrace)
   {
      System.out.println("stack trace:");

      for (StackTraceElement stackTraceElement : stackTrace)
      {
         System.out.println(stackTraceElement.toString());
      }
   }

   private class VariableChangeAndStackTrace
   {
      private final Thread thread;
      private final YoVariable variableOne;
      private final YoVariable variableTwo;
      private final double variableValue;
      private final StackTraceElement[] stackTrace;

      public VariableChangeAndStackTrace(Thread thread, YoVariable variableOne, YoVariable variableTwo, double variableValue,
                                         StackTraceElement[] stackTrace)
      {
         this.thread = thread;
         this.variableOne = variableOne;
         this.variableTwo = variableTwo;
         this.variableValue = variableValue;
         this.stackTrace = stackTrace;
      }

   }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy