// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/assert.h"

#include "vm/dart_api_impl.h"
#include "vm/dart_api_state.h"
#include "vm/globals.h"
#include "vm/profiler.h"
#include "vm/unit_test.h"

namespace dart {

class ProfileSampleBufferTestHelper {
 public:
  static intptr_t IterateCount(const Isolate* isolate,
                               const SampleBuffer& sample_buffer) {
    intptr_t c = 0;
    Sample* sample = Sample::Allocate();
    for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
      sample_buffer.CopySample(i, sample);
      if (sample->isolate() != isolate) {
        continue;
      }
      c++;
    }
    free(sample);
    return c;
  }


  static intptr_t IterateSumPC(const Isolate* isolate,
                               const SampleBuffer& sample_buffer) {
    intptr_t c = 0;
    Sample* sample = Sample::Allocate();
    for (intptr_t i = 0; i < sample_buffer.capacity(); i++) {
      sample_buffer.CopySample(i, sample);
      if (sample->isolate() != isolate) {
        continue;
      }
      c += sample->At(0);
    }
    free(sample);
    return c;
  }
};


TEST_CASE(ProfilerSampleBufferWrapTest) {
  SampleBuffer* sample_buffer = new SampleBuffer(3);
  Isolate* i = reinterpret_cast<Isolate*>(0x1);
  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
  Sample* s;
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  s->SetAt(0, 2);
  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  s->SetAt(0, 4);
  EXPECT_EQ(6, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  s->SetAt(0, 6);
  EXPECT_EQ(12, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  s->SetAt(0, 8);
  EXPECT_EQ(18, ProfileSampleBufferTestHelper::IterateSumPC(i, *sample_buffer));
  delete sample_buffer;
}


TEST_CASE(ProfilerSampleBufferIterateTest) {
  SampleBuffer* sample_buffer = new SampleBuffer(3);
  Isolate* i = reinterpret_cast<Isolate*>(0x1);
  EXPECT_EQ(0, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
  Sample* s;
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  EXPECT_EQ(1, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  EXPECT_EQ(2, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
  s = sample_buffer->ReserveSample();
  s->Init(Sample::kIsolateSample, i, 0, 0);
  EXPECT_EQ(3, ProfileSampleBufferTestHelper::IterateCount(i, *sample_buffer));
  delete sample_buffer;
}

}  // namespace dart
