/*
 * 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>

#if defined(__BIONIC__)

#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
#include <sys/_system_properties.h>

#include <benchmark/benchmark.h>

extern void* __system_property_area__;

// Do not exceed 512, that is about the largest number of properties
// that can be created with the current property area size.
#define TEST_NUM_PROPS \
    Arg(1)->Arg(4)->Arg(16)->Arg(64)->Arg(128)->Arg(256)->Arg(512)

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

    const char* android_data = getenv("ANDROID_DATA");
    if (android_data == NULL) {
      printf("ANDROID_DATA environment variable not set\n");
      return;
    }
    char dir_template[PATH_MAX];
    snprintf(dir_template, sizeof(dir_template), "%s/local/tmp/prop-XXXXXX", android_data);
    char* dirname = mkdtemp(dir_template);
    if (!dirname) {
      printf("making temp file for test state failed (is %s/local/tmp writable?): %s\n",
             android_data, strerror(errno));
      return;
    }

    old_pa = __system_property_area__;
    __system_property_area__ = NULL;

    pa_dirname = dirname;
    pa_filename = pa_dirname + "/__properties__";

    __system_property_set_filename(pa_filename.c_str());
    __system_property_area_init();

    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_property_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;
  }

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

    __system_property_area__ = old_pa;

    __system_property_set_filename(PROP_FILENAME);
    unlink(pa_filename.c_str());
    rmdir(pa_dirname.c_str());

    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:
  std::string pa_dirname;
  std::string pa_filename;
  void* old_pa;
};

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

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

  while (state.KeepRunning()) {
    char value[PROP_VALUE_MAX];
    __system_property_get(pa.names[random() % nprops], value);
  }
}
BENCHMARK(BM_property_get)->TEST_NUM_PROPS;

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

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

  while (state.KeepRunning()) {
    __system_property_find(pa.names[random() % nprops]);
  }
}
BENCHMARK(BM_property_find)->TEST_NUM_PROPS;

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

  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] = __system_property_find(pa.names[random() % nprops]);
  }

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

  delete[] pinfo;
}
BENCHMARK(BM_property_read)->TEST_NUM_PROPS;

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

  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] = __system_property_find(pa.names[random() % nprops]);
  }

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

  delete[] pinfo;
}
BENCHMARK(BM_property_serial)->TEST_NUM_PROPS;

#endif  // __BIONIC__
