/** Tests the standard aggregation behavior */
  @Test
  public void testAggregation() {
    AggregateSummaryStatistics aggregate = new AggregateSummaryStatistics();
    SummaryStatistics setOneStats = aggregate.createContributingStatistics();
    SummaryStatistics setTwoStats = aggregate.createContributingStatistics();

    Assert.assertNotNull("The set one contributing stats are null", setOneStats);
    Assert.assertNotNull("The set two contributing stats are null", setTwoStats);
    Assert.assertNotSame("Contributing stats objects are the same", setOneStats, setTwoStats);

    setOneStats.addValue(2);
    setOneStats.addValue(3);
    setOneStats.addValue(5);
    setOneStats.addValue(7);
    setOneStats.addValue(11);
    Assert.assertEquals("Wrong number of set one values", 5, setOneStats.getN());
    Assert.assertTrue(
        "Wrong sum of set one values", Precision.equals(28.0, setOneStats.getSum(), 1));

    setTwoStats.addValue(2);
    setTwoStats.addValue(4);
    setTwoStats.addValue(8);
    Assert.assertEquals("Wrong number of set two values", 3, setTwoStats.getN());
    Assert.assertTrue(
        "Wrong sum of set two values", Precision.equals(14.0, setTwoStats.getSum(), 1));

    Assert.assertEquals("Wrong number of aggregate values", 8, aggregate.getN());
    Assert.assertTrue("Wrong aggregate sum", Precision.equals(42.0, aggregate.getSum(), 1));
  }
  @Test
  public void testAggregateSpecialValues() {
    double[] totalSample = {Double.POSITIVE_INFINITY, 2, 3, Double.NaN, 5};
    double[][] subSamples = {{Double.POSITIVE_INFINITY, 2}, {3}, {Double.NaN}, {5}};

    // Compute combined stats directly
    SummaryStatistics totalStats = new SummaryStatistics();
    for (int i = 0; i < totalSample.length; i++) {
      totalStats.addValue(totalSample[i]);
    }

    // Now compute subsample stats individually and aggregate
    SummaryStatistics[] subSampleStats = new SummaryStatistics[5];
    for (int i = 0; i < 4; i++) {
      subSampleStats[i] = new SummaryStatistics();
    }
    Collection<SummaryStatistics> aggregate = new ArrayList<SummaryStatistics>();
    for (int i = 0; i < 4; i++) {
      for (int j = 0; j < subSamples[i].length; j++) {
        subSampleStats[i].addValue(subSamples[i][j]);
      }
      aggregate.add(subSampleStats[i]);
    }

    // Compare values
    StatisticalSummaryValues aggregatedStats = AggregateSummaryStatistics.aggregate(aggregate);
    assertEquals(totalStats.getSummary(), aggregatedStats, 10E-12);
  }
  /** Similar to {@link #testAggregate()} but operating on {@link StatisticalSummary} instead. */
  @Test
  public void testAggregateStatisticalSummary() {

    // Generate a random sample and random partition
    double[] totalSample = generateSample();
    double[][] subSamples = generatePartition(totalSample);
    int nSamples = subSamples.length;

    // Compute combined stats directly
    SummaryStatistics totalStats = new SummaryStatistics();
    for (int i = 0; i < totalSample.length; i++) {
      totalStats.addValue(totalSample[i]);
    }

    // Now compute subsample stats individually and aggregate
    SummaryStatistics[] subSampleStats = new SummaryStatistics[nSamples];
    for (int i = 0; i < nSamples; i++) {
      subSampleStats[i] = new SummaryStatistics();
    }
    Collection<StatisticalSummary> aggregate = new ArrayList<StatisticalSummary>();
    for (int i = 0; i < nSamples; i++) {
      for (int j = 0; j < subSamples[i].length; j++) {
        subSampleStats[i].addValue(subSamples[i][j]);
      }
      aggregate.add(subSampleStats[i].getSummary());
    }

    // Compare values
    StatisticalSummary aggregatedStats = AggregateSummaryStatistics.aggregate(aggregate);
    assertEquals(totalStats.getSummary(), aggregatedStats, 10E-12);
  }
  /**
   * Verify that aggregating over a partition gives the same results as direct computation.
   *
   * <p>1) Randomly generate a dataset of 10-100 values from [-100, 100] 2) Divide the dataset it
   * into 2-5 partitions 3) Create an AggregateSummaryStatistic and ContributingStatistics for each
   * partition 4) Compare results from the AggregateSummaryStatistic with values returned by a
   * single SummaryStatistics instance that is provided the full dataset
   */
  @Test
  public void testAggregationConsistency() {

    // Generate a random sample and random partition
    double[] totalSample = generateSample();
    double[][] subSamples = generatePartition(totalSample);
    int nSamples = subSamples.length;

    // Create aggregator and total stats for comparison
    AggregateSummaryStatistics aggregate = new AggregateSummaryStatistics();
    SummaryStatistics totalStats = new SummaryStatistics();

    // Create array of component stats
    SummaryStatistics componentStats[] = new SummaryStatistics[nSamples];

    for (int i = 0; i < nSamples; i++) {

      // Make componentStats[i] a contributing statistic to aggregate
      componentStats[i] = aggregate.createContributingStatistics();

      // Add values from subsample
      for (int j = 0; j < subSamples[i].length; j++) {
        componentStats[i].addValue(subSamples[i][j]);
      }
    }

    // Compute totalStats directly
    for (int i = 0; i < totalSample.length; i++) {
      totalStats.addValue(totalSample[i]);
    }

    /*
     * Compare statistics in totalStats with aggregate.
     * Note that guaranteed success of this comparison depends on the
     * fact that <aggregate> gets values in exactly the same order
     * as <totalStats>.
     *
     */
    Assert.assertEquals(totalStats.getSummary(), aggregate.getSummary());
  }
 /**
  * Get the Variance of all the stats that are watched, for all the stats added with add() since
  * the creation of this <tt>HammerSummaryStats</tt>
  *
  * @return The Variance of all the stats JSON.
  */
 public String getAggregateVarianceJSON() {
   String str =
       String.format(
           FakeUserStats.jsonMediaStreamStatsTemplate,
           -1, // ssrc not needed here
           aggregateDownloadJitterMs.getVariance(),
           aggregateDownloadPercentLoss.getVariance(),
           aggregateDownloadRateKiloBitPerSec.getVariance(),
           aggregateJitterBufferDelayMs.getVariance(),
           aggregateJitterBufferDelayPackets.getVariance(),
           aggregateNbDiscarded.getVariance(),
           aggregateNbDiscardedFull.getVariance(),
           aggregateNbDiscardedLate.getVariance(),
           aggregateNbDiscardedReset.getVariance(),
           aggregateNbDiscardedShrink.getVariance(),
           aggregateNbFec.getVariance(),
           aggregateNbPackets.getVariance(),
           aggregateNbPacketsLost.getVariance(),
           aggregateNbReceivedBytes.getVariance(),
           aggregateNbSentBytes.getVariance(),
           aggregatePacketQueueCountPackets.getVariance(),
           aggregatePacketQueueSize.getVariance(),
           aggregatePercentDiscarded.getVariance(),
           aggregateRttMs.getVariance(),
           aggregateUploadJitterMs.getVariance(),
           aggregateUploadPercentLoss.getVariance(),
           aggregateUploadRateKiloBitPerSec.getVariance());
   return str;
 }
 /**
  * Create new <tt>SummaryStatistics</tt> from the <tt>AggregateSummaryStatistics</tt> for all
  * the stream's stats that are watched.
  */
 public void clear() {
   downloadJitterMs = aggregateDownloadJitterMs.createContributingStatistics();
   downloadPercentLoss = aggregateDownloadPercentLoss.createContributingStatistics();
   downloadRateKiloBitPerSec = aggregateDownloadRateKiloBitPerSec.createContributingStatistics();
   jitterBufferDelayMs = aggregateJitterBufferDelayMs.createContributingStatistics();
   jitterBufferDelayPackets = aggregateJitterBufferDelayPackets.createContributingStatistics();
   nbDiscarded = aggregateNbDiscarded.createContributingStatistics();
   nbDiscardedFull = aggregateNbDiscardedFull.createContributingStatistics();
   nbDiscardedLate = aggregateNbDiscardedLate.createContributingStatistics();
   nbDiscardedReset = aggregateNbDiscardedReset.createContributingStatistics();
   nbDiscardedShrink = aggregateNbDiscardedShrink.createContributingStatistics();
   nbFec = aggregateNbFec.createContributingStatistics();
   nbPackets = aggregateNbPackets.createContributingStatistics();
   nbPacketsLost = aggregateNbPacketsLost.createContributingStatistics();
   nbReceivedBytes = aggregateNbReceivedBytes.createContributingStatistics();
   nbSentBytes = aggregateNbSentBytes.createContributingStatistics();
   packetQueueCountPackets = aggregatePacketQueueCountPackets.createContributingStatistics();
   packetQueueSize = aggregatePacketQueueSize.createContributingStatistics();
   percentDiscarded = aggregatePercentDiscarded.createContributingStatistics();
   rttMs = aggregateRttMs.createContributingStatistics();
   uploadJitterMs = aggregateUploadJitterMs.createContributingStatistics();
   uploadPercentLoss = aggregateUploadPercentLoss.createContributingStatistics();
   uploadRateKiloBitPerSec = aggregateUploadRateKiloBitPerSec.createContributingStatistics();
 }