/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "monitor_pool.h"

#include "common_runtime_test.h"
#include "monitor-inl.h"
#include "monitor.h"
#include "scoped_thread_state_change-inl.h"
#include "thread-current-inl.h"

namespace art HIDDEN {

class MonitorPoolTest : public CommonRuntimeTest {};

class RandGen {
 public:
  explicit RandGen(uint32_t seed) : val_(seed) {}

  uint32_t next() {
    val_ = val_ * 48271 % 2147483647 + 13;
    return val_;
  }

  uint32_t val_;
};

static void VerifyMonitor(Monitor* mon, Thread* self) {
  // Check whether the monitor id is correct.
  EXPECT_EQ(MonitorPool::MonitorIdFromMonitor(mon), mon->GetMonitorId());
  // Check whether the monitor id agrees with the compuation.
  EXPECT_EQ(MonitorPool::ComputeMonitorId(mon, self), mon->GetMonitorId());
  // Check whether we can use the monitor ID to get the monitor.
  EXPECT_EQ(mon, MonitorPool::MonitorFromMonitorId(mon->GetMonitorId()));
}

TEST_F(MonitorPoolTest, MonitorPoolTest) {
  std::vector<Monitor*> monitors;
  RandGen r(0x1234);

  // 1) Create and release monitors without increasing the storage.

  // Number of max alive monitors before resize.
  // Note: for correct testing, make sure this is corresponding to monitor-pool's initial size.
  const size_t kMaxUsage = 28;

  Thread* self = Thread::Current();
  ScopedObjectAccess soa(self);

  // Allocate and release monitors.
  for (size_t i = 0; i < 1000 ; i++) {
    bool alloc;
    if (monitors.size() == 0) {
      alloc = true;
    } else if (monitors.size() == kMaxUsage) {
      alloc = false;
    } else {
      // Random decision.
      alloc = r.next() % 2 == 0;
    }

    if (alloc) {
      Monitor* mon = MonitorPool::CreateMonitor(
          self, MonitorOwner::FromThread(self), nullptr, static_cast<int32_t>(i));
      monitors.push_back(mon);

      VerifyMonitor(mon, self);
    } else {
      // Release a random monitor.
      size_t index = r.next() % monitors.size();
      Monitor* mon = monitors[index];
      monitors.erase(monitors.begin() + index);

      // Recheck the monitor.
      VerifyMonitor(mon, self);

      MonitorPool::ReleaseMonitor(self, mon);
    }
  }

  // Loop some time.

  for (size_t i = 0; i < 10; ++i) {
    // 2.1) Create enough monitors to require new chunks.
    size_t target_size = monitors.size() + 2*kMaxUsage;
    while (monitors.size() < target_size) {
      Monitor* mon = MonitorPool::CreateMonitor(
          self, MonitorOwner::FromThread(self), nullptr, static_cast<int32_t>(-monitors.size()));
      monitors.push_back(mon);

      VerifyMonitor(mon, self);
    }

    // 2.2) Verify all monitors.
    for (Monitor* mon : monitors) {
      VerifyMonitor(mon, self);
    }

    // 2.3) Release a number of monitors randomly.
    for (size_t j = 0; j < kMaxUsage; j++) {
      // Release a random monitor.
      size_t index = r.next() % monitors.size();
      Monitor* mon = monitors[index];
      monitors.erase(monitors.begin() + index);

      MonitorPool::ReleaseMonitor(self, mon);
    }
  }

  // Check and release all remaining monitors.
  for (Monitor* mon : monitors) {
    VerifyMonitor(mon, self);
    MonitorPool::ReleaseMonitor(self, mon);
  }
}

}  // namespace art
