/*
 * 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 <gtest/gtest.h>

#include <errno.h>
#include <limits.h>
#include <locale.h>

#include "utils.h"

TEST(locale, localeconv) {
  EXPECT_STREQ(".", localeconv()->decimal_point);
  EXPECT_STREQ("", localeconv()->thousands_sep);
  EXPECT_STREQ("", localeconv()->grouping);
  EXPECT_STREQ("", localeconv()->int_curr_symbol);
  EXPECT_STREQ("", localeconv()->currency_symbol);
  EXPECT_STREQ("", localeconv()->mon_decimal_point);
  EXPECT_STREQ("", localeconv()->mon_thousands_sep);
  EXPECT_STREQ("", localeconv()->mon_grouping);
  EXPECT_STREQ("", localeconv()->positive_sign);
  EXPECT_STREQ("", localeconv()->negative_sign);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_frac_digits);
  EXPECT_EQ(CHAR_MAX, localeconv()->frac_digits);
  EXPECT_EQ(CHAR_MAX, localeconv()->p_cs_precedes);
  EXPECT_EQ(CHAR_MAX, localeconv()->p_sep_by_space);
  EXPECT_EQ(CHAR_MAX, localeconv()->n_cs_precedes);
  EXPECT_EQ(CHAR_MAX, localeconv()->n_sep_by_space);
  EXPECT_EQ(CHAR_MAX, localeconv()->p_sign_posn);
  EXPECT_EQ(CHAR_MAX, localeconv()->n_sign_posn);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_p_cs_precedes);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_p_sep_by_space);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_n_cs_precedes);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_n_sep_by_space);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_p_sign_posn);
  EXPECT_EQ(CHAR_MAX, localeconv()->int_n_sign_posn);
}

TEST(locale, setlocale) {
  EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, nullptr));
  EXPECT_STREQ("C.UTF-8", setlocale(LC_CTYPE, nullptr));

  errno = 0;
  EXPECT_EQ(nullptr, setlocale(-1, nullptr));
  EXPECT_ERRNO(EINVAL);
  errno = 0;
  EXPECT_EQ(nullptr, setlocale(13, nullptr));
  EXPECT_ERRNO(EINVAL);

#if defined(__BIONIC__)
  // The "" locale is implementation-defined. For bionic, it's the C.UTF-8 locale, which is
  // pretty much all we support anyway.
  // glibc will give us something like "en_US.UTF-8", depending on the user's configuration.
  EXPECT_STREQ("C.UTF-8", setlocale(LC_ALL, ""));
#endif
  EXPECT_STREQ("C", setlocale(LC_ALL, "C"));
  EXPECT_STREQ("C", setlocale(LC_ALL, "POSIX"));

  errno = 0;
  EXPECT_EQ(nullptr, setlocale(LC_ALL, "this-is-not-a-locale"));
  EXPECT_ERRNO(ENOENT);  // POSIX specified, not an implementation detail!
}

TEST(locale, newlocale_invalid_category_mask) {
  errno = 0;
  EXPECT_EQ(nullptr, newlocale(1 << 20, "C", nullptr));
  EXPECT_ERRNO(EINVAL);
}

TEST(locale, newlocale_NULL_locale_name) {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wnonnull"
  errno = 0;
  EXPECT_EQ(nullptr, newlocale(LC_ALL, nullptr, nullptr));
  EXPECT_ERRNO(EINVAL);
#pragma clang diagnostic pop
}

TEST(locale, newlocale_bad_locale_name) {
  errno = 0;
  EXPECT_EQ(nullptr, newlocale(LC_ALL, "this-is-not-a-locale", nullptr));
  EXPECT_ERRNO(ENOENT);  // POSIX specified, not an implementation detail!
}

TEST(locale, newlocale) {
  locale_t l = newlocale(LC_ALL, "C", nullptr);
  ASSERT_TRUE(l != nullptr);
  freelocale(l);
}

TEST(locale, duplocale) {
  locale_t cloned_global = duplocale(LC_GLOBAL_LOCALE);
  ASSERT_TRUE(cloned_global != nullptr);
  freelocale(cloned_global);
}

TEST(locale, uselocale) {
  locale_t original = uselocale(nullptr);
  EXPECT_FALSE(original == nullptr);
  EXPECT_EQ(LC_GLOBAL_LOCALE, original);

  locale_t n = newlocale(LC_ALL, "C", nullptr);
  EXPECT_FALSE(n == nullptr);
  EXPECT_FALSE(n == original);

  locale_t old = uselocale(n);
  EXPECT_TRUE(old == original);

  EXPECT_EQ(n, uselocale(nullptr));
}

TEST(locale, mb_cur_max) {
  // We can't reliably test the behavior with setlocale(3) or the behavior for
  // initial program conditions because (unless we're the only test that was
  // run), another test has almost certainly called uselocale(3) in this thread.
  // See b/16685652.
  locale_t cloc = newlocale(LC_ALL, "C", nullptr);
  locale_t cloc_utf8 = newlocale(LC_ALL, "C.UTF-8", nullptr);

  locale_t old_locale = uselocale(cloc);
  ASSERT_EQ(1U, MB_CUR_MAX);
  uselocale(cloc_utf8);
  ASSERT_EQ(4U, MB_CUR_MAX);

  uselocale(old_locale);
  freelocale(cloc);
  freelocale(cloc_utf8);
}
