/*
 * Copyright (C) 2012 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 <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include <string>
#include <vector>

#include <android-base/file.h>

using namespace std::literals;

#if defined(__BIONIC__)

#include <sys/system_properties.h>

#include <benchmark/benchmark.h>
#include <system_properties/system_properties.h>
#include "util.h"

struct LocalPropertyTestState {
  explicit LocalPropertyTestState(int nprops)
      : nprops(nprops), valid(false), system_properties_(false) {
    static const char prop_name_chars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_.";

    valid = system_properties_.AreaInit(dir_.path, nullptr, true);
    if (!valid) {
      printf("Failed to initialize properties, terminating...\n");
      exit(1);
    }

    names = new char* [nprops];
    name_lens = new int[nprops];
    values = new char* [nprops];
    value_lens = new int[nprops];

    srandom(nprops);

    for (int i = 0; i < nprops; i++) {
      // Make sure the name has at least 10 characters to make
      // it very unlikely to generate the same random name.
      name_lens[i] = (random() % (PROP_NAME_MAX - 10)) + 10;
      names[i] = new char[PROP_NAME_MAX + 1];
      size_t prop_name_len = sizeof(prop_name_chars) - 1;
      for (int j = 0; j < name_lens[i]; j++) {
        if (j == 0 || names[i][j-1] == '.' || j == name_lens[i] - 1) {
          // Certain values are not allowed:
          // - Don't start name with '.'
          // - Don't allow '.' to appear twice in a row
          // - Don't allow the name to end with '.'
          // This assumes that '.' is the last character in the
          // array so that decrementing the length by one removes
          // the value from the possible values.
          prop_name_len--;
        }
        names[i][j] = prop_name_chars[random() % prop_name_len];
      }
      names[i][name_lens[i]] = 0;

      // Make sure the value contains at least 1 character.
      value_lens[i] = (random() % (PROP_VALUE_MAX - 1)) + 1;
      values[i] = new char[PROP_VALUE_MAX];
      for (int j = 0; j < value_lens[i]; j++) {
        values[i][j] = prop_name_chars[random() % (sizeof(prop_name_chars) - 1)];
      }

      if (system_properties_.Add(names[i], name_lens[i], values[i], value_lens[i]) < 0) {
        printf("Failed to add a property, terminating...\n");
        printf("%s = %.*s\n", names[i], value_lens[i], values[i]);
        exit(1);
      }
    }

    valid = true;
  }

  SystemProperties& system_properties() {
    return system_properties_;
  }

  ~LocalPropertyTestState() {
    if (!valid) {
      return;
    }

    system_properties_.contexts_->FreeAndUnmap();
    if (system_properties_.appcompat_override_contexts_) {
      system_properties_.appcompat_override_contexts_->FreeAndUnmap();
    }

    for (int i = 0; i < nprops; i++) {
      delete names[i];
      delete values[i];
    }
    delete[] names;
    delete[] name_lens;
    delete[] values;
    delete[] value_lens;
  }

 public:
  const int nprops;
  char** names;
  int* name_lens;
  char** values;
  int* value_lens;
  bool valid;

 private:
  SystemProperties system_properties_;
  TemporaryDir dir_;
};

static void BM_property_get(benchmark::State& state) {
  const size_t nprops = state.range(0);

  LocalPropertyTestState pa(nprops);
  if (!pa.valid) return;

  while (state.KeepRunning()) {
    char value[PROP_VALUE_MAX];
    pa.system_properties().Get(pa.names[random() % nprops], value);
  }
}
BIONIC_BENCHMARK_WITH_ARG(BM_property_get, "NUM_PROPS");

static void BM_property_find(benchmark::State& state) {
  const size_t nprops = state.range(0);

  LocalPropertyTestState pa(nprops);
  if (!pa.valid) return;

  while (state.KeepRunning()) {
    pa.system_properties().Find(pa.names[random() % nprops]);
  }
}
BIONIC_BENCHMARK_WITH_ARG(BM_property_find, "NUM_PROPS");

static void BM_property_read(benchmark::State& state) {
  const size_t nprops = state.range(0);

  LocalPropertyTestState pa(nprops);
  if (!pa.valid) return;

  const prop_info** pinfo = new const prop_info*[nprops];
  char propvalue[PROP_VALUE_MAX];

  for (size_t i = 0; i < nprops; ++i) {
    pinfo[i] = pa.system_properties().Find(pa.names[random() % nprops]);
  }

  size_t i = 0;
  while (state.KeepRunning()) {
    pa.system_properties().Read(pinfo[i], nullptr, propvalue);
    i = (i + 1) % nprops;
  }

  delete[] pinfo;
}
BIONIC_BENCHMARK_WITH_ARG(BM_property_read, "NUM_PROPS");

static void BM_property_serial(benchmark::State& state) {
  const size_t nprops = state.range(0);

  LocalPropertyTestState pa(nprops);
  if (!pa.valid) return;

  const prop_info** pinfo = new const prop_info*[nprops];
  for (size_t i = 0; i < nprops; ++i) {
    pinfo[i] = pa.system_properties().Find(pa.names[random() % nprops]);
  }

  size_t i = 0;
  while (state.KeepRunning()) {
    __system_property_serial(pinfo[i]);
    i = (i + 1) % nprops;
  }

  delete[] pinfo;
}
BIONIC_BENCHMARK_WITH_ARG(BM_property_serial, "NUM_PROPS");

// This benchmarks find the actual properties currently set on the system and accessible by the
// user that runs this benchmark (aka this is best run as root).  It is not comparable between
// devices, nor even boots, but is useful to understand the the real end-to-end speed, including
// costs to find the correct property file within /dev/__properties__.
static void BM_property_find_real(benchmark::State& state) {
  std::vector<std::string> properties;
  __system_property_foreach(
      [](const prop_info* pi, void* cookie) {
        __system_property_read_callback(pi,
                                        [](void* cookie, const char* name, const char*, unsigned) {
                                          auto properties =
                                              reinterpret_cast<std::vector<std::string>*>(cookie);
                                          properties->emplace_back(name);
                                        },
                                        cookie);
      },
      &properties);

  while (state.KeepRunning()) {
    for (const auto& property : properties) {
      __system_property_find(property.c_str());
    }
  }
}
BIONIC_BENCHMARK(BM_property_find_real);

#endif  // __BIONIC__
