text:
#include <iostream>

#include "gtest/gtest.h"

#include "dbcommon/function/string-binary-function.h"
#include "dbcommon/log/debug-logger.h"
#include "dbcommon/testutil/function-utils.h"
#include "dbcommon/testutil/scalar-utils.h"
#include "dbcommon/testutil/vector-utils.h"

namespace dbcommon {

TEST(TestFunction, string_char_length) {
  FunctionUtility fu(FuncKind::STRING_CHAR_LENGTH);
  auto ret = fu.generatePara<0, Vector>("NULL");

  auto expect = fu.generatePara<0, Vector>("3 8 5 NULL 3 2 4");
  auto strs =
      fu.generatePara<1, Vector>("cat black的今天 sheep NULL fry is good");
  std::vector<Datum> params{ret, strs};
  fu.test(params.data(), params.size(), expect);

  {
    auto expect = fu.generatePara<0, Vector>("10 7 8 3");
    auto strs =
        fu.generatePara<1, Vector>("i am a stu, nic to,meet you,   ", ',');
    std::vector<Datum> params{ret, strs};
    fu.test(params.data(), params.size(), expect);
  }
}

TEST(TestFunction, string_octet_length) {
  FunctionUtility fu(FuncKind::STRING_OCTET_LENGTH);
  auto ret = fu.generatePara<0, Vector>("NULL");

  auto expect = fu.generatePara<0, Vector>("3 5 5 NULL 3 2 4");
  auto strs = fu.generatePara<1, Vector>("cat black sheep NULL fry is good");
  std::vector<Datum> params{ret, strs};
  fu.test(params.data(), params.size(), expect);
}

TEST(TestFunction, string_like) {
  FunctionUtility fu(FuncKind::STRING_LIKE);
  SelectList ret;

  auto strs = fu.generatePara<1, Vector>(
      "cat NULL sheep NULL fry is good peer flee 你ee");

  {
    LOG_TESTING("non-ANSI pattern");

    SelectList expect{7, 9};
    auto pattern = fu.generatePara<2, Scalar>("_ee%");
    std::vector<Datum> params{CreateDatum(&ret), strs, pattern};
    fu.test(params.data(), params.size(), CreateDatum(&expect));
  }

  {
    LOG_TESTING("ANSI pattern");
    SelectList expect{4, 7};
    auto pattern = fu.generatePara<2, Scalar>("%r%");
    std::vector<Datum> params{CreateDatum(&ret), strs, pattern};
    fu.test(params.data(), params.size(), CreateDatum(&expect));
  }
}

TEST(TestFunction, string_not_like) {
  FunctionUtility fu(FuncKind::STRING_NOT_LIKE);
  SelectList ret;

  auto strs = fu.generatePara<1, Vector>(
      "cat NULL sheep NULL fry is good peer flee 你ee try");

  {
    LOG_TESTING("non-ANSI pattern");

    auto pattern = fu.generatePara<2, Scalar>("_ry");
    SelectList expect{0, 2, 5, 6, 7, 8, 9};
    std::vector<Datum> params{CreateDatum(&ret), strs, pattern};
    fu.test(params.data(), params.size(), CreateDatum(&expect));
  }

  {
    LOG_TESTING("ANSI pattern");
    auto pattern = fu.generatePara<2, Scalar>("%ee%");
    SelectList expect{0, 4, 5, 6, 10};
    std::vector<Datum> params{CreateDatum(&ret), strs, pattern};
    fu.test(params.data(), params.size(), CreateDatum(&expect));
  }
}

TEST(TestFunction, string_substring_nolen) {
  FunctionUtility fu(FuncKind::STRING_SUBSTRING_NOLEN);
  auto ret = fu.generatePara<0, Vector>("NULL");

  {
    LOG_TESTING("Vector - Vector with ascii input");
    auto expect = fu.generatePara<0, Vector>("cat,ack,NULL,,b,66ccff", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,b,66ccff", ',');
    auto pos = fu.generatePara<2, Vector>("0 3 1 2 1 -1");
    std::vector<Datum> params{ret, strs, pos};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Vector with utf8 input");
    auto expect = fu.generatePara<0, Vector>("一二三四,一二三四,,二三四", ',');
    auto strs =
        fu.generatePara<1, Vector>("一二三四,一二三四,一二三四,一二三四", ',');
    auto pos = fu.generatePara<2, Vector>("0 -1 5 2");
    std::vector<Datum> params{ret, strs, pos};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar with ascii input");
    auto expect = fu.generatePara<0, Vector>("at,lack,NULL,,", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,b", ',');
    auto pos = fu.generatePara<2, Scalar>("2");
    std::vector<Datum> params{ret, strs, pos};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar with null input");
    auto expect = fu.generatePara<0, Vector>("NULL,NULL,NULL,NULL,NULL", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,b", ',');
    auto pos = fu.generatePara<2, Scalar>("NULL");
    std::vector<Datum> params{ret, strs, pos};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector with ascii input");
    auto expect = fu.generatePara<0, Vector>("abcdefg,cdefg,,abcdefg", ',');
    auto strs = fu.generatePara<1, Scalar>("abcdefg");
    auto pos = fu.generatePara<2, Vector>("0 3 10 -1");
    std::vector<Datum> params{ret, strs, pos};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector with null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL NULL");
    auto strs = fu.generatePara<1, Scalar>("NULL");
    auto pos = fu.generatePara<2, Vector>("0 3 10 -1");
    std::vector<Datum> params{ret, strs, pos};
    fu.test(params.data(), params.size(), expect);
  }
}

TEST(TestFunction, string_substring) {
  FunctionUtility fu(FuncKind::STRING_SUBSTRING);
  auto ret = fu.generatePara<0, Vector>("NULL");

  {
    LOG_TESTING("Vector - Vector - Vector with ascii input");
    auto expect = fu.generatePara<0, Vector>("at,,NULL,,ccff", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,66ccff", ',');
    auto pos = fu.generatePara<2, Vector>("2 1 1 1 3");
    auto len = fu.generatePara<3, Vector>("4 0 1 2 4");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Vector - Vector with utf8 input");
    auto expect = fu.generatePara<0, Vector>("二三四五,,一,三四五", ',');
    auto strs = fu.generatePara<1, Vector>(
        "一二三四五,一二三四五,一二三四五,一二三四五", ',');
    auto pos = fu.generatePara<2, Vector>("2 1 1 3");
    auto len = fu.generatePara<3, Vector>("4 0 1 6");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Vector - Vector with error input");
    auto strs = fu.generatePara<1, Vector>("error");
    auto pos = fu.generatePara<2, Vector>("2");
    auto len = fu.generatePara<3, Vector>("-1");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Vector - Vector - Scalar with ascii input");
    auto expect = fu.generatePara<0, Vector>("at,blac,NULL,,ccff", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,66ccff", ',');
    auto pos = fu.generatePara<2, Vector>("2 1 1 1 3");
    auto len = fu.generatePara<3, Scalar>("4");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Vector - Scalar with error input");
    auto strs = fu.generatePara<1, Vector>("error");
    auto pos = fu.generatePara<2, Vector>("2");
    auto len = fu.generatePara<3, Scalar>("-1");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Vector - Vector - Scalar with null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL NULL NULL");
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,66ccff", ',');
    auto pos = fu.generatePara<2, Vector>("2 1 1 1 3");
    auto len = fu.generatePara<3, Scalar>("NULL");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar - Vector with ascii input");
    auto expect = fu.generatePara<0, Vector>("cat,bl,NULL,,66cc", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,66ccff", ',');
    auto pos = fu.generatePara<2, Scalar>("1");
    auto len = fu.generatePara<3, Vector>("4 2 1 1 4");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar - Vector with error input");
    auto strs = fu.generatePara<1, Vector>("error");
    auto pos = fu.generatePara<2, Scalar>("1");
    auto len = fu.generatePara<3, Vector>("-1");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Vector - Scalar - Vector with null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL NULL NULL");
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,66ccff", ',');
    auto pos = fu.generatePara<2, Scalar>("NULL");
    auto len = fu.generatePara<3, Vector>("4 2 1 1 4");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar - Scalar with ascii input");
    auto expect = fu.generatePara<0, Vector>("at,lac,NULL,,,6cc", ',');
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,,b,66ccff", ',');
    auto pos = fu.generatePara<2, Scalar>("2");
    auto len = fu.generatePara<3, Scalar>("3");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar - Scalar with error input");
    auto strs = fu.generatePara<1, Vector>("error");
    auto pos = fu.generatePara<2, Scalar>("2");
    auto len = fu.generatePara<3, Scalar>("-1");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Vector - Scalar - Scalar with pos null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL NULL");
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,b", ',');
    auto pos = fu.generatePara<2, Scalar>("NULL");
    auto len = fu.generatePara<3, Scalar>("3");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Vector - Scalar - Scalar with len null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL NULL");
    auto strs = fu.generatePara<1, Vector>("cat,black,NULL,b", ',');
    auto pos = fu.generatePara<2, Scalar>("2");
    auto len = fu.generatePara<3, Scalar>("NULL");
    std::vector<Datum> params{ret, strs, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector - Vector with ascii input");
    auto expect = fu.generatePara<0, Vector>("bcde,abc,,ab", ',');
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Vector>("2 1 -2 -1");
    auto len = fu.generatePara<3, Vector>("8 3 1 4");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector - Vector with error input");
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Vector>("2");
    auto len = fu.generatePara<3, Vector>("-1");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Scalar - Vector - Vector with null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL NULL");
    auto str = fu.generatePara<1, Scalar>("NULL");
    auto pos = fu.generatePara<2, Vector>("2 1 -2 -1");
    auto len = fu.generatePara<3, Vector>("8 3 1 4");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Scalar - Vector with ascii input");
    auto expect = fu.generatePara<0, Vector>("abcde,a,", ',');
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Scalar>("-1");
    auto len = fu.generatePara<3, Vector>("8 3 1");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Scalar - Vector with error input");
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Scalar>("-1");
    auto len = fu.generatePara<3, Vector>("-1");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Scalar - Scalar - Vector with str null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL");
    auto str = fu.generatePara<1, Scalar>("NULL");
    auto pos = fu.generatePara<2, Scalar>("-1");
    auto len = fu.generatePara<3, Vector>("8 3 1");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Scalar - Vector with pos null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL");
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Scalar>("NULL");
    auto len = fu.generatePara<3, Vector>("8 3 1");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector - Scalar with ascii input");
    auto expect = fu.generatePara<0, Vector>(",abc,e", ',');
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Vector>("-2 1 5");
    auto len = fu.generatePara<3, Scalar>("3");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector - Scalar with error input");
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Vector>("-2 1 5");
    auto len = fu.generatePara<3, Scalar>("-1");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_SUBSTRING_ERROR);
  }

  {
    LOG_TESTING("Scalar - Vector - Scalar with str null input");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL");
    auto str = fu.generatePara<1, Scalar>("NULL");
    auto pos = fu.generatePara<2, Vector>("-2 1 5");
    auto len = fu.generatePara<3, Scalar>("3");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }

  {
    LOG_TESTING("Scalar - Vector - Scalar with len null input");
    auto ret = fu.generatePara<0, Vector>("NULL");
    auto expect = fu.generatePara<0, Vector>("NULL NULL NULL");
    auto str = fu.generatePara<1, Scalar>("abcde");
    auto pos = fu.generatePara<2, Vector>("-2 1 5");
    auto len = fu.generatePara<3, Scalar>("NULL");
    std::vector<Datum> params{ret, str, pos, len};
    fu.test(params.data(), params.size(), expect);
  }
}

TEST(TestFunction, string_lower) {
  FunctionUtility fu(FuncKind::STRING_LOWER);
  auto ret = fu.generatePara<0, Vector>("NULL");

  auto expect = fu.generatePara<0, Vector>("cat NULL sheep NULL 009bb is good");
  auto strs = fu.generatePara<1, Vector>("caT NULL shEEp NULL 009bb is GOOD");
  std::vector<Datum> params{ret, strs};
  fu.test(params.data(), params.size(), expect);
}

TEST(TestFunction, string_upper) {
  FunctionUtility fu(FuncKind::STRING_UPPER);
  auto ret = fu.generatePara<0, Vector>("NULL");

  auto expect =
      fu.generatePara<0, Vector>("CAT NULL SHEEP NULL 009BB IS GOOD 中国CHINA");
  auto strs =
      fu.generatePara<1, Vector>("caT NULL shEEp NULL 009bb is GOOD 中国China");
  std::vector<Datum> params{ret, strs};
  fu.test(params.data(), params.size(), expect);
}

TEST(TestFunction, string_concat) {
  FunctionUtility fu(FuncKind::STRING_CONCAT);
  VectorUtility vuString(TypeKind::STRINGID);
  ScalarUtility suString(TypeKind::STRINGID);
  auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

  // Vector concat Vector in normal input
  {
    LOG_TESTING("Vector || Vector with noramal input");
    auto str1 = vuString.generateVector("abc,NULL,D e F,1258,G2333", ',');
    auto str2 = vuString.generateVector("NULL,xxx,112,G 2,x80", ',');
    auto concat =
        vuString.generateVector("NULL,NULL,D e F112,1258G 2,G2333x80", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(str1.get()),
                              CreateDatum(str2.get())};
    fu.test(params.data(), params.size(), CreateDatum(concat.get()));
  }

  // Vector concat Vector in NULL input
  {
    LOG_TESTING("Vector || Vector with null vector");
    auto str1 = vuString.generateVector("abc,cde,D e F,1258,G2333", ',');
    auto str2 = vuString.generateVector("NULL,NULL,NULL,NULL,NULL", ',');
    auto concat = vuString.generateVector("NULL,NULL,NULL,NULL,NULL", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(str1.get()),
                              CreateDatum(str2.get())};
    fu.test(params.data(), params.size(), CreateDatum(concat.get()));
  }

  // Vector concat Scalar while scalar is not null
  {
    LOG_TESTING("Vector || Scalar with normal input");
    auto str1 = vuString.generateVector("a,b 2333,NULL,cdEf,101,8x", ',');
    auto str2 = suString.generateScalar("t_");
    auto concat =
        vuString.generateVector("at_,b 2333t_,NULL,cdEft_,101t_,8xt_", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(str1.get()),
                              CreateDatum(&str2)};
    fu.test(params.data(), params.size(), CreateDatum(concat.get()));
  }

  // Vector concat Scalar while scalar is null
  {
    LOG_TESTING("Vector || Scalar with scalar is null");
    auto str1 = vuString.generateVector("a,b 2333,NULL,cdEf,101,8x", ',');
    auto str2 = suString.generateScalar("NULL");
    auto concat = vuString.generateVector("NULL,NULL,NULL,NULL,NULL,NULL", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(str1.get()),
                              CreateDatum(&str2)};
    fu.test(params.data(), params.size(), CreateDatum(concat.get()));
  }

  // Scalar concat Vector while scalar is not null
  {
    LOG_TESTING("Scalar || Vector with normal input");
    auto str1 = suString.generateScalar("a_");
    auto str2 = vuString.generateVector("b NULL NULL a");
    auto concat = vuString.generateVector("a_b NULL NULL a_a");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&str1),
                              CreateDatum(str2.get())};
    fu.test(params.data(), params.size(), CreateDatum(concat.get()));
  }

  // Scalar concat Vector while scalar is null
  {
    LOG_TESTING("scalar || vector with scalar is null");
    auto str1 = suString.generateScalar("NULL");
    auto str2 = vuString.generateVector("b NULL NULL a");
    auto concat = vuString.generateVector("NULL NULL NULL NULL");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&str1),
                              CreateDatum(str2.get())};
    fu.test(params.data(), params.size(), CreateDatum(concat.get()));
  }
}

TEST(TestFunction, string_position) {
  FunctionUtility fu(FuncKind::STRING_POSITION);
  VectorUtility vuString(TypeKind::STRINGID);
  VectorUtility vuInteger(TypeKind::INTID);
  ScalarUtility suString(TypeKind::STRINGID);
  auto ret = Vector::BuildVector(TypeKind::INTID, true);

  {
    LOG_TESTING("Vector in Vector with normal input");
    auto lhs = vuString.generateVector(
        "ab,NULL,,1258,a b,abcd, b c,abcabcabcabcabcabd", ',');
    auto rhs = vuString.generateVector(
        "abc,xxx,,NULL,abb,abc,a b c,abcabcabcabcabcabcabd", ',');
    auto position = vuInteger.generateVector("1 NULL 1 NULL 0 0 2 4");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(rhs.get()),
                              CreateDatum(lhs.get())};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Vector in Vector with normal input");
    auto lhs = vuString.generateVector("一2三,,ab西,六六六,我 2,三四", ',');
    auto rhs = vuString.generateVector(
        "一2三4,xxx,一二ab西,七七七,我2我 2快乐水,一二三四", ',');
    auto position = vuInteger.generateVector("1 1 3 0 3 3");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(rhs.get()),
                              CreateDatum(lhs.get())};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Vector in Vector with NULL input");
    auto lhs = vuString.generateVector("ab,NULL,21,1258,a b,abcd, b c", ',');
    auto rhs =
        vuString.generateVector("NULL,NULL,NULL,NULL,NULL,NULL,NULL", ',');
    auto position =
        vuInteger.generateVector("NULL NULL NULL NULL NULL NULL NULL");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(rhs.get()),
                              CreateDatum(lhs.get())};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Vector in Scalar with normal input");
    auto lhs = vuString.generateVector(
        "ab,NULL,abab,abcb,a b,abcabdab, ab,abcabcabcabcabda,", ',');
    auto rhs = suString.generateScalar("abcabd");
    auto position = vuInteger.generateVector("1 NULL 0 0 0 0 0 0 1");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&rhs),
                              CreateDatum(lhs.get())};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Vector in Scalar with null input");
    auto lhs =
        vuString.generateVector("ab,NULL,abab,abcb,a b,abcabdab, ab", ',');
    auto rhs = suString.generateScalar("NULL");
    auto position =
        vuInteger.generateVector("NULL NULL NULL NULL NULL NULL NULL");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&rhs),
                              CreateDatum(lhs.get())};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Scalar in Vector with normal input");
    auto lhs = suString.generateScalar("23");
    auto rhs = vuString.generateVector("233,NULL,666,", ',');
    auto position = vuInteger.generateVector("1 NULL 0 0");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(rhs.get()),
                              CreateDatum(&lhs)};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Scalar in Vector with null input");
    auto lhs = suString.generateScalar("NULL");
    auto rhs = vuString.generateVector("abc,NULL,ababcabd,a bcabd,abdabc", ',');
    auto position = vuInteger.generateVector("NULL NULL NULL NULL NULL");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(rhs.get()),
                              CreateDatum(&lhs)};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }

  {
    LOG_TESTING("Scalar in Vector with special input");
    auto lhs = suString.generateScalar("233233233233234");
    auto rhs = vuString.generateVector(
        "233233233233233234,NULL,6666666666666666", ',');
    auto position = vuInteger.generateVector("4 NULL 0");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(rhs.get()),
                              CreateDatum(&lhs)};
    fu.test(params.data(), params.size(), CreateDatum(position.get()));
  }
}

INSTANTIATE_TEST_CASE_P(string_initcap, TestFunction,
                        ::testing::Values(TestFunctionEntry{
                            FuncKind::STRING_INITCAP,
                            "Vector{delimiter=,}: Cat,NULL,I Like Fish, "
                            "52a*C,2b,Love中国,厉害abc,Abc,1b3,",
                            {"Vector{delimiter=,}: caT,NULL,i like fish, "
                             "52a*c,2B,love中国,厉害ABC,Abc,1b3,"}}));

TEST(TestFunction, string_initcap) {
  FunctionUtility fu(FuncKind::STRING_INITCAP);
  VectorUtility vuString(TypeKind::STRINGID);

  auto strs = vuString.generateVector(
      "caT,NULL,i like fish, 52a*c,2B,love中国,厉害ABC,Abc,1b3,", ',');
  auto initcap = vuString.generateVector(
      "Cat,NULL,I Like Fish, 52a*C,2b,Love中国,厉害abc,Abc,1b3,", ',');
  auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

  std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get())};
  fu.test(params.data(), params.size(), CreateDatum(initcap.get()));
}

TEST(TestFunction, string_ascii) {
  FunctionUtility fu(FuncKind::STRING_ASCII);
  VectorUtility vuString(TypeKind::STRINGID);
  VectorUtility vuInteger(TypeKind::INTID);

  auto strs = vuString.generateVector("abc, 1,92,Я,中国,𒓔,NULL,", ',');
  auto ascii = vuInteger.generateVector("97 32 57 1071 20013 74964 NULL 0");
  auto ret = Vector::BuildVector(TypeKind::INTID, true);

  std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get())};
  fu.test(params.data(), params.size(), CreateDatum(ascii.get()));
}

TEST(TestFunction, string_varchar) {
  FunctionUtility fu(FuncKind::STRING_VARCHAR);

  VectorUtility vuStr(TypeKind::STRINGID);
  VectorUtility vuInt(TypeKind::INTID);
  VectorUtility vuBoo(TypeKind::BOOLEANID);

  ScalarUtility suStr(TypeKind::STRINGID);
  ScalarUtility suInt(TypeKind::INTID);
  ScalarUtility suBoo(TypeKind::BOOLEANID);

  // Case 1.1: vec vec vec
  {
    LOG_TESTING("string varchar: vec vec vec");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = vuInt.generateVector("6 6 6");
    auto exps = vuBoo.generateVector("t t t");

    auto rtns = vuStr.generateVector("a ab NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(lens.get()), CreateDatum(exps.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 1.2: vec vec vec
  {
    LOG_TESTING("string varchar: vec vec vec");

    auto strs = vuStr.generateVector("abc abcd");
    auto lens = vuInt.generateVector("6 7");
    auto exps = vuBoo.generateVector("f f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(lens.get()), CreateDatum(exps.get())};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }

  {
    LOG_TESTING("string varchar: vec vec vec");

    auto strs = vuStr.generateVector("中 a中国 NULL");
    auto lens = vuInt.generateVector("6 6 6");
    auto exps = vuBoo.generateVector("t t t");

    auto rtns = vuStr.generateVector("中 a中 NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(lens.get()), CreateDatum(exps.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 2.1: vec vec val(NOT NULL)
  {
    LOG_TESTING("string varchar: vec vec val(NOT NULL)");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = vuInt.generateVector("6 6 6");
    auto exp = suBoo.generateScalar("t");

    auto rtns = vuStr.generateVector("a ab NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(lens.get()), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 2.2: vec vec val(NULL)
  {
    LOG_TESTING("string varchar: vec vec val(NULL)");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = vuInt.generateVector("6 6 6");
    auto exp = suBoo.generateScalar("NULL");

    auto rtns = vuStr.generateVector("NULL NULL NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(lens.get()), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 2.3: vec vec val(NOT NULL)
  {
    LOG_TESTING("string varchar: vec vec val(NOT NULL)");

    auto strs = vuStr.generateVector("abc abcd");
    auto lens = vuInt.generateVector("6 7");
    auto exp = suBoo.generateScalar("f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(lens.get()), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }

  // Case 3.1: vec val(NOT NULL) vec
  {
    LOG_TESTING("string varchar: vec val(NOT NULL) vec");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = suInt.generateScalar("6");
    auto exp = vuBoo.generateVector("t t t");

    auto rtns = vuStr.generateVector("a ab NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(&lens), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 3.2: vec val(NULL) vec
  {
    LOG_TESTING("string varchar: vec val(NULL) vec");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = suInt.generateScalar("NULL");
    auto exp = vuBoo.generateVector("t t t");

    auto rtns = vuStr.generateVector("NULL NULL NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(&lens), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 3.3: vec val(NOT NULL) vec
  {
    LOG_TESTING("string varchar: vec val(NOT NULL) vec");

    auto strs = vuStr.generateVector("abc abcd");
    auto lens = suInt.generateScalar("6");
    auto exp = vuBoo.generateVector("f f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(&lens), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }

  // Case 4.1: vec val(NOT NULL) val(NOT NULL)
  {
    LOG_TESTING("string varchar: vec val(NOT NULL) val(NOT NULL");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = suInt.generateScalar("6");
    auto exp = suBoo.generateScalar("t");

    auto rtns = vuStr.generateVector("a ab NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(&lens), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 4.2: vec val(NULL) val(NULL)
  {
    LOG_TESTING("string varchar: vec val(NULL) val((NULL");

    auto strs = vuStr.generateVector("a abc NULL");
    auto lens = suInt.generateScalar("NULL");
    auto exp = suBoo.generateScalar("NULL");

    auto rtns = vuStr.generateVector("NULL NULL NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(&lens), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 4.3: vec val(NOT NULL) val(NOT NULL)
  {
    LOG_TESTING("string varchar: vec val(NOT NULL) val(NOT NULL");

    auto strs = vuStr.generateVector("abc abcd");
    auto lens = suInt.generateScalar("6");
    auto exp = suBoo.generateScalar("f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(strs.get()),
                              CreateDatum(&lens), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }

  // Case 5.1: val(NOT NULL) vec vec
  {
    LOG_TESTING("string varchar: val(NOT NULL) vec vec");

    auto strs = suStr.generateScalar("abc");
    auto lens = vuInt.generateVector("6 7 8");
    auto exp = vuBoo.generateVector("t t NULL");

    auto rtns = vuStr.generateVector("ab abc NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(lens.get()), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 5.2: val(NULL) vec vec
  {
    LOG_TESTING("string varchar: val(NULL) vec vec");

    auto strs = suStr.generateScalar("NULL");
    auto lens = vuInt.generateVector("6 7 8");
    auto exp = vuBoo.generateVector("t t NULL");

    auto rtns = vuStr.generateVector("NULL NULL NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(lens.get()), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 5.3: val(NOT NULL) vec vec
  {
    LOG_TESTING("string varchar: val(NOT NULL) vec vec");

    auto strs = suStr.generateScalar("abcde");
    auto lens = vuInt.generateVector("6 7 8");
    auto exp = vuBoo.generateVector("f f f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(lens.get()), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }

  // Case 6.1: val(NOT NULL) vec val(NOT NULL)
  {
    LOG_TESTING("string varchar: val(NOT NULL) vec val(NOT NULL)");

    auto strs = suStr.generateScalar("abc");
    auto lens = vuInt.generateVector("6 7 NULL");
    auto exp = suBoo.generateScalar("t");

    auto rtns = vuStr.generateVector("ab abc NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(lens.get()), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 6.2: val(NULL) vec val(NULL)
  {
    LOG_TESTING("string varchar: val(NULL) vec val(NULL)");

    auto strs = suStr.generateScalar("NULL");
    auto lens = vuInt.generateVector("6 7 NULL");
    auto exp = suBoo.generateScalar("NULL");

    auto rtns = vuStr.generateVector("NULL NULL NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(lens.get()), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 6.3: val(NOT NULL) vec val(NOT NULL)
  {
    LOG_TESTING("string varchar: val(NOT NULL) vec val(NOT NULL)");

    auto strs = suStr.generateScalar("abcd");
    auto lens = vuInt.generateVector("6 7");
    auto exp = suBoo.generateScalar("f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(lens.get()), CreateDatum(&exp)};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }

  // Case 7.1: val(NOT NULL) val(NOT NULL) vec
  {
    LOG_TESTING("string varchar: val(NOT NULL) val(NOT NULL) vec");

    auto strs = suStr.generateScalar("abc");
    auto lens = suInt.generateScalar("6");
    auto exp = vuBoo.generateVector("t t NULL");

    auto rtns = vuStr.generateVector("ab ab NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(&lens), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 7.2: val(NULL) val(NULL) vec
  {
    LOG_TESTING("string varchar: val(NULL) val(NULL)s vec");

    auto strs = suStr.generateScalar("NULL");
    auto lens = suInt.generateScalar("NULL");
    auto exp = vuBoo.generateVector("t t NULL");

    auto rtns = vuStr.generateVector("NULL NULL NULL");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(&lens), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(rtns.get()));
  }

  // Case 7.3: val(NOT NULL) val(NOT NULL) vec
  {
    LOG_TESTING("string varchar: val(NOT NULL) val(NOT NULL) vec");

    auto strs = suStr.generateScalar("abc");
    auto lens = suInt.generateScalar("6");
    auto exp = vuBoo.generateVector("f f");

    auto rets = Vector::BuildVector(TypeKind::STRINGID, true);
    std::vector<Datum> params{CreateDatum(rets.get()), CreateDatum(&strs),
                              CreateDatum(&lens), CreateDatum(exp.get())};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_STRING_DATA_RIGHT_TRUNCATION);
  }
}

TEST(TestFunction, string_ltrim_blank) {
  FunctionUtility fu(FuncKind::STRING_LTRIM_BLANK);
  VectorUtility vuStr(TypeKind::STRINGID);

  {
    LOG_TESTING("trim vector from vector with null input");
    auto lhs = vuStr.generateVector("NULL,abc,NULL, a bc d ,  aa bc dd  ", ',');
    auto exp = vuStr.generateVector("NULL,abc,NULL,a bc d ,aa bc dd  ", ',');
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(lhs.get())};

    fu.test(params.data(), params.size(), CreateDatum(exp.get()));
  }

  {
    auto strs = vuStr.generateVector(
        " caT,NULL,  shEEp,NULL,   009bb, is,  GOOD,   中国China", ',');
    auto trim = vuStr.generateVector(
        "caT,NULL,shEEp,NULL,009bb,is,GOOD,中国China", ',');
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }
}

TEST(TestFunction, string_ltrim_chars) {
  FunctionUtility fu(FuncKind::STRING_LTRIM_CHARS);
  VectorUtility vu(TypeKind::STRINGID);
  ScalarUtility su(TypeKind::STRINGID);

  {
    auto strs = vu.generateVector(
        "XcaT NULL YYshEEp NULL ZZZ009bb xis yyGOOD zzz中国China");
    auto chrs = vu.generateVector("X A Y B Z x y z");
    auto trim =
        vu.generateVector("caT NULL shEEp NULL 009bb is GOOD 中国China");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(chrs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }

  {
    auto strs = su.generateScalar("XYZxyz");
    auto chrs = vu.generateVector("X NULL x XY XYZ");
    auto trim = vu.generateVector("YZxyz NULL XYZxyz Zxyz xyz");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&strs),
                              CreateDatum(chrs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }

  {
    auto strs = vu.generateVector(
        "XcaT NULL YYshEEp NULL ZZZ009bb xis yyGOOD zzz中国China");
    auto trim =
        vu.generateVector("caT NULL shEEp NULL 009bb is GOOD 中国China");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    auto set = su.generateScalar("XYZxyz");
    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(&set)};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }
}

TEST(TestFunction, string_rtrim_blank) {
  FunctionUtility fu(FuncKind::STRING_RTRIM_BLANK);
  VectorUtility vu(TypeKind::STRINGID);

  auto strs = vu.generateVector(
      "caT ,NULL,shEEp  ,NULL,009bb   ,is ,GOOD  ,中国China   ", ',');
  auto trim =
      vu.generateVector("caT,NULL,shEEp,NULL,009bb,is,GOOD,中国China", ',');
  auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

  std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get())};
  fu.test(params.data(), params.size(), CreateDatum(trim.get()));
}

TEST(TestFunction, string_rtrim_chars) {
  FunctionUtility fu(FuncKind::STRING_RTRIM_CHARS);
  VectorUtility vu(TypeKind::STRINGID);
  ScalarUtility su(TypeKind::STRINGID);

  {
    auto strs = vu.generateVector(
        "caTX NULL shEEpYY NULL 009bbZZZ isx GOODyy 中国Chinazzz");
    auto chrs = vu.generateVector("X XYZ Y, xyz Z x y z");
    auto trim =
        vu.generateVector("caT NULL shEEp NULL 009bb is GOOD 中国China");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(chrs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }

  {
    auto strs = vu.generateVector(
        "caTX NULL shEEpYY NULL 009bbZZZ isx GOODyy 中国Chinazzz");
    auto trim =
        vu.generateVector("caT NULL shEEp NULL 009bb is GOOD 中国China");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    auto set = su.generateScalar("XYZxyz");
    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(&set)};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }

  {
    auto strs = su.generateScalar("XYZxyz");
    auto chrs = vu.generateVector("z NULL yz xyz");
    auto trim = vu.generateVector("XYZxy NULL XYZx XYZ");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&strs),
                              CreateDatum(chrs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }
}

TEST(TestFunction, string_btrim_blank) {
  FunctionUtility fu(FuncKind::STRING_BTRIM_BLANK);
  VectorUtility vu(TypeKind::STRINGID);

  auto strs = vu.generateVector(
      " caT ,NULL,  shEEp  ,NULL,   009bb   , is ,  GOOD  ,   中国China   ",
      ',');
  auto trim =
      vu.generateVector("caT,NULL,shEEp,NULL,009bb,is,GOOD,中国China", ',');
  auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

  std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get())};
  fu.test(params.data(), params.size(), CreateDatum(trim.get()));
}

TEST(TestFunction, string_btrim_chars) {
  FunctionUtility fu(FuncKind::STRING_BTRIM_CHARS);
  VectorUtility vu(TypeKind::STRINGID);
  ScalarUtility su(TypeKind::STRINGID);

  {
    auto strs = vu.generateVector(
        "xcaTX NULL yyshEEpYY NULL zzz009bbZZZ Xisx YYGOODyy ZZZ中国Chinazzz");
    auto chrs = vu.generateVector("xX xyz yY XYZ zZ xX yY zZ");
    auto trim =
        vu.generateVector("caT NULL shEEp NULL 009bb is GOOD 中国China");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(chrs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }

  {
    auto strs = vu.generateVector(
        "xcaTX NULL yyshEEpYY NULL zzz009bbZZZ Xisx YYGOODyy ZZZ中国Chinazzz");
    auto trim =
        vu.generateVector("caT NULL shEEp NULL 009bb is GOOD 中国China");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    auto set = su.generateScalar("XYZxyz");
    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(&set)};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }

  {
    auto strs = su.generateScalar("xyzXYZ");
    auto chrs = vu.generateVector("NULL x xy xyZ");
    auto trim = vu.generateVector("NULL yzXYZ zXYZ zXY");
    auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&strs),
                              CreateDatum(chrs.get())};
    fu.test(params.data(), params.size(), CreateDatum(trim.get()));
  }
}

INSTANTIATE_TEST_CASE_P(
    string_repeat, TestFunction,
    ::testing::Values(
        TestFunctionEntry{
            FuncKind::STRING_REPEAT,
            "Vector{delimiter=,}: abc,NULL,AbCAbCAbC,,小可爱小可爱,",
            {"Vector{delimiter=,}: abc,NULL,AbC,bca,小可爱,",
             "Vector: 1 2 3 0 2 2"}},
        TestFunctionEntry{FuncKind::STRING_REPEAT,
                          "Error",
                          {"Vector: str", "Vector: 2147483640"},
                          ERRCODE_PROGRAM_LIMIT_EXCEEDED},
        TestFunctionEntry{
            FuncKind::STRING_REPEAT,
            "Vector{delimiter=,}: abcabc,NULL,AbCAbC,小可爱小可爱,",
            {"Vector{delimiter=,}: abc,NULL,AbC,小可爱,", "Scalar: 2"}},
        TestFunctionEntry{FuncKind::STRING_REPEAT,
                          "Error",
                          {"Vector: str", "Scalar: 2147483640"},
                          ERRCODE_PROGRAM_LIMIT_EXCEEDED},
        TestFunctionEntry{
            FuncKind::STRING_REPEAT,
            "Vector: NULL NULL NULL NULL NULL",
            {"Vector{delimiter=,}: abc,NULL,AbC,小可爱,", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_REPEAT,
                          "Vector{delimiter=,}: 2数2数,,NULL",
                          {"Scalar: 2数", "Vector: 2 0 NULL"}},
        TestFunctionEntry{FuncKind::STRING_REPEAT,
                          "Error",
                          {"Scalar: str", "Vector: 2147483640"},
                          ERRCODE_PROGRAM_LIMIT_EXCEEDED},
        TestFunctionEntry{FuncKind::STRING_REPEAT,
                          "Vector: NULL NULL NULL",
                          {"Scalar: NULL", "Vector: 2 0 4"}}));

TEST(TestFunction, string_repeat) {
  FunctionUtility fu(FuncKind::STRING_REPEAT);
  VectorUtility vuString(TypeKind::STRINGID);
  VectorUtility vuInteger(TypeKind::INTID);
  ScalarUtility suString(TypeKind::STRINGID);
  ScalarUtility suInteger(TypeKind::INTID);
  auto ret = Vector::BuildVector(TypeKind::STRINGID, true);

  {
    LOG_TESTING("Vector repeat Vecotr");
    auto strs = vuString.generateVector("abc,NULL,AbC,bca,小可爱,", ',');
    auto dup = vuInteger.generateVector("1 2 3 0 2 2");
    auto repeat =
        vuString.generateVector("abc,NULL,AbCAbCAbC,,小可爱小可爱,", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(dup.get())};
    fu.test(params.data(), params.size(), CreateDatum(repeat.get()));
  }

  {
    LOG_TESTING("Vector repeat Vecotr with error");
    auto strs = vuString.generateVector("str");
    auto dup = vuInteger.generateVector("2147483640");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(dup.get())};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_PROGRAM_LIMIT_EXCEEDED);
  }

  {
    LOG_TESTING("Vector repeat Scalar with normal input");
    auto strs = vuString.generateVector("abc,NULL,AbC,小可爱,", ',');
    auto dup = suInteger.generateScalar("2");
    auto repeat =
        vuString.generateVector("abcabc,NULL,AbCAbC,小可爱小可爱,", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(&dup)};
    fu.test(params.data(), params.size(), CreateDatum(repeat.get()));
  }

  {
    LOG_TESTING("Vector repeat Scalar with error");
    auto strs = vuString.generateVector("str");
    auto dup = suInteger.generateScalar("2147483640");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(&dup)};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_PROGRAM_LIMIT_EXCEEDED);
  }

  {
    LOG_TESTING("Vector repeat Scalar with null input");
    auto strs = vuString.generateVector("abc,NULL,AbC,小可爱,", ',');
    auto dup = suInteger.generateScalar("NULL");
    auto repeat = vuString.generateVector("NULL,NULL,NULL,NULL,NULL", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(strs.get()),
                              CreateDatum(&dup)};
    fu.test(params.data(), params.size(), CreateDatum(repeat.get()));
  }

  {
    LOG_TESTING("Scalar repeat Vector with normal input");
    auto strs = suString.generateScalar("2数");
    auto dup = vuInteger.generateVector("2 0 NULL");
    auto repeat = vuString.generateVector("2数2数,,NULL", ',');

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&strs),
                              CreateDatum(dup.get())};
    fu.test(params.data(), params.size(), CreateDatum(repeat.get()));
  }

  {
    LOG_TESTING("Scalar repeat Vector with error");
    auto strs = suString.generateScalar("str");
    auto dup = vuInteger.generateVector("2147483640");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&strs),
                              CreateDatum(dup.get())};
    fu.test(params.data(), params.size(), CreateDatum(0),
            ERRCODE_PROGRAM_LIMIT_EXCEEDED);
  }

  {
    LOG_TESTING("Scalar repeat Vector with null input");
    auto strs = suString.generateScalar("NULL");
    auto dup = vuInteger.generateVector("1 0 5");
    auto repeat = vuString.generateVector("NULL NULL NULL");

    std::vector<Datum> params{CreateDatum(ret.get()), CreateDatum(&strs),
                              CreateDatum(dup.get())};
    fu.test(params.data(), params.size(), CreateDatum(repeat.get()));
  }
}

INSTANTIATE_TEST_CASE_P(
    string_chr, TestFunction,
    ::testing::Values(
        TestFunctionEntry{FuncKind::STRING_CHR,
                          "Vector: \x01 A \x7F \u0080 ÿ Ā ✐ 𒓔 NULL",
                          {"Vector: 1 65 127 128 255 256 10000 74964 NULL"}},
        TestFunctionEntry{FuncKind::STRING_CHR,
                          "Error",
                          {"Vector: 2333333"},
                          ERRCODE_PROGRAM_LIMIT_EXCEEDED},
        TestFunctionEntry{FuncKind::STRING_CHR,
                          "Error",
                          {"Vector: 0"},
                          ERRCODE_PROGRAM_LIMIT_EXCEEDED}));

INSTANTIATE_TEST_CASE_P(
    string_bpchar, TestFunction,
    ::testing::Values(
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector{delimiter=,}: a ,ab,NULL",
                          {"Vector{delimiter=,}: a,ab ,NULL", "Vector: 6 6 6",
                           "Vector: t t t"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Vector: abc", "Vector: 6", "Vector: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector{delimiter=,}: 中 ,中国,a中国,NULL",
                          {"Vector{delimiter=,}: 中,中国 ,a中国B,NULL",
                           "Vector: 6 6 7 6", "Vector: t t t t"}},
        TestFunctionEntry{
            FuncKind::STRING_BPCHAR,
            "Vector{delimiter=,}: a ,ab,NULL",
            {"Vector{delimiter=,}: a,ab ,NULL", "Vector: 6 6 6", "Scalar: t"}},
        TestFunctionEntry{
            FuncKind::STRING_BPCHAR,
            "Vector: NULL NULL NULL",
            {"Vector: a ab NULL", "Vector: 6 6 6", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Vector: abc", "Vector: 6", "Scalar: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION},
        TestFunctionEntry{
            FuncKind::STRING_BPCHAR,
            "Vector{delimiter=,}: a ,ab,NULL",
            {"Vector{delimiter=,}: a,ab ,NULL", "Scalar: 6", "Vector: t t t"}},
        TestFunctionEntry{
            FuncKind::STRING_BPCHAR,
            "Vector: NULL NULL NULL",
            {"Vector: a ab NULL", "Scalar: NULL", "Vector: t t t"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Vector: abc", "Scalar: 6", "Vector: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION},
        TestFunctionEntry{
            FuncKind::STRING_BPCHAR,
            "Vector{delimiter=,}: a ,ab,NULL",
            {"Vector{delimiter=,}: a,ab ,NULL", "Scalar: 6", "Scalar: t"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector: NULL NULL NULL",
                          {"Vector: a ab NULL", "Scalar: NULL", "Scalar: t"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Vector: abc", "Scalar: 6", "Scalar: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector: ab abc NULL",
                          {"Scalar: abc", "Vector: 6 7 8", "Vector: t t NULL"}},
        TestFunctionEntry{
            FuncKind::STRING_BPCHAR,
            "Vector: NULL NULL NULL",
            {"Scalar: NULL", "Vector: 6 7 8", "Vector: t t NULL"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Scalar: abc", "Vector: 6", "Vector: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector: ab abc NULL",
                          {"Scalar: abc", "Vector: 6 7 NULL", "Scalar: t"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector: NULL NULL NULL",
                          {"Scalar: abc", "Vector: 6 7 NULL", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Scalar: abc", "Vector: 6", "Scalar: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector: ab ab NULL",
                          {"Scalar: abc", "Scalar: 6", "Vector: t t NULL"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Vector: NULL NULL NULL",
                          {"Scalar: NULL", "Scalar: 6", "Vector: t t NULL"}},
        TestFunctionEntry{FuncKind::STRING_BPCHAR,
                          "Error",
                          {"Scalar: abc", "Scalar: 6", "Vector: f"},
                          ERRCODE_STRING_DATA_RIGHT_TRUNCATION}));

INSTANTIATE_TEST_CASE_P(
    string_lpad, TestFunction,
    ::testing::Values(
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: 1二1一二 3一2三 66嘻嘻ff 我喜欢娃哈哈 吃鸡",
            {"Vector: 一二 一2三 66嘻嘻ff 娃哈哈 吃鸡100次",
             "Vector: 5 4 6 6 2", "Vector: 1二 3二1 哎哎哎 我喜欢 x"}},
        TestFunctionEntry{FuncKind::STRING_LPAD,
                          "Vector: 121xy 3abc 66ccff NULL",
                          {"Vector: xy abc 66ccff NULL", "Vector: 5 4 6 5",
                           "Vector: 12 321 xxx zzz"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: zxcxy zabc 66ccff NULL",
            {"Vector: xy abc 66ccff ixx", "Vector: 5 4 6 NULL", "Scalar: zxc"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: NULL NULL NULL",
            {"Vector: xy abc 66ccff", "Vector: 5 4 6", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_LPAD,
                          "Vector: 121xy 32abc 66ccf NULL",
                          {"Vector: xy abc 66ccff uvw", "Scalar: 5",
                           "Vector: 12 321 xy NULL"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: NULL NULL NULL",
            {"Vector: xy abc 66ccff", "Scalar: NULL", "Vector: 12 321 xy"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: 123xy 12abc 66ccf NULL",
            {"Vector: xy abc 66ccff NULL", "Scalar: 5", "Scalar: 123"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: NULL NULL NULL",
            {"Vector: xy abc 66ccff", "Scalar: NULL", "Scalar: 123"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: 66ccf 66ccff z66ccff NULL",
            {"Scalar: 66ccff", "Vector: 5 6 7 NULL", "Vector: x y z x"}},
        TestFunctionEntry{FuncKind::STRING_LPAD,
                          "Vector: NULL NULL NULL",
                          {"Scalar: NULL", "Vector: 4 5 6", "Vector: 1 2 3"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: 66c 66ccff xx66ccff NULL",
            {"Scalar: 66ccff", "Vector: 3 6 8 NULL", "Scalar: x"}},
        TestFunctionEntry{FuncKind::STRING_LPAD,
                          "Vector: NULL NULL NULL",
                          {"Scalar: 66ccff", "Vector: 4 5 6", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_LPAD,
                          "Vector: x6ccf y6ccf z6ccf NULL",
                          {"Scalar: 6ccf", "Scalar: 5", "Vector: x y z NULL"}},
        TestFunctionEntry{
            FuncKind::STRING_LPAD,
            "Vector: NULL NULL NULL",
            {"Scalar: 66ccff", "Scalar: NULL", "Vector: x y z"}}));

INSTANTIATE_TEST_CASE_P(
    string_rpad, TestFunction,
    ::testing::Values(
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: 一二1二1 一2三3 66嘻嘻ff 娃哈哈我喜欢 吃鸡",
            {"Vector: 一二 一2三 66嘻嘻ff 娃哈哈 吃鸡100次",
             "Vector: 5 4 6 6 2", "Vector: 1二 3二1 哎哎哎 我喜欢 x"}},
        TestFunctionEntry{FuncKind::STRING_RPAD,
                          "Vector: xy121 abc3 66ccff NULL",
                          {"Vector: xy abc 66ccff NULL", "Vector: 5 4 6 5",
                           "Vector: 12 321 xxx zzz"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: xyzxc abcz 66ccff NULL",
            {"Vector: xy abc 66ccff ixx", "Vector: 5 4 6 NULL", "Scalar: zxc"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: NULL NULL NULL",
            {"Vector: xy abc 66ccff", "Vector: 5 4 6", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_RPAD,
                          "Vector: xy121 abc32 66ccf NULL",
                          {"Vector: xy abc 66ccff uvw", "Scalar: 5",
                           "Vector: 12 321 xy NULL"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: NULL NULL NULL",
            {"Vector: xy abc 66ccff", "Scalar: NULL", "Vector: 12 321 xy"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: xy123 abc12 66ccf NULL",
            {"Vector: xy abc 66ccff NULL", "Scalar: 5", "Scalar: 123"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: NULL NULL NULL",
            {"Vector: xy abc 66ccff", "Scalar: NULL", "Scalar: 123"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: 66ccf 66ccff 66ccffz NULL",
            {"Scalar: 66ccff", "Vector: 5 6 7 NULL", "Vector: x y z x"}},
        TestFunctionEntry{FuncKind::STRING_RPAD,
                          "Vector: NULL NULL NULL",
                          {"Scalar: NULL", "Vector: 4 5 6", "Vector: 1 2 3"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: 66c 66ccff 66ccffxx NULL",
            {"Scalar: 66ccff", "Vector: 3 6 8 NULL", "Scalar: x"}},
        TestFunctionEntry{FuncKind::STRING_RPAD,
                          "Vector: NULL NULL NULL",
                          {"Scalar: 66ccff", "Vector: 4 5 6", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_RPAD,
                          "Vector: 6ccfx 6ccfy 6ccfz NULL",
                          {"Scalar: 6ccf", "Scalar: 5", "Vector: x y z NULL"}},
        TestFunctionEntry{
            FuncKind::STRING_RPAD,
            "Vector: NULL NULL NULL",
            {"Scalar: 66ccff", "Scalar: NULL", "Vector: x y z"}}));

INSTANTIATE_TEST_CASE_P(
    string_lpad_nofill, TestFunction,
    ::testing::Values(
        TestFunctionEntry{
            FuncKind::STRING_LPAD_NOFILL,
            "Vector{delimiter=,}:  一二三,  二三四,66嘻嘻ff,二三四",
            {"Vector: 一二三 二三四 66嘻嘻ff 二三四五", "Vector: 4 5 6 3"}},
        TestFunctionEntry{FuncKind::STRING_LPAD_NOFILL,
                          "Vector{delimiter=,}:  xyz,  abc,66ccff,NULL",
                          {"Vector: xyz abc 66ccff NULL", "Vector: 4 5 6 7"}},
        TestFunctionEntry{FuncKind::STRING_LPAD_NOFILL,
                          "Vector{delimiter=,}:  xyz,1abc,66cc,NULL",
                          {"Vector: xyz 1abc 66ccff NULL", "Scalar: 4"}},
        TestFunctionEntry{FuncKind::STRING_LPAD_NOFILL,
                          "Vector: NULL NULL NULL",
                          {"Vector: xyz abc 66ccff", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_LPAD_NOFILL,
                          "Vector{delimiter=,}: xyz,xyz1, xyz1,NULL",
                          {"Scalar: xyz1", "Vector: 3 4 5 NULL"}},
        TestFunctionEntry{FuncKind::STRING_LPAD_NOFILL,
                          "Vector: NULL NULL NULL",
                          {"Scalar: NULL", "Vector: 4 5 6"}}));

INSTANTIATE_TEST_CASE_P(
    string_rpad_nofill, TestFunction,
    ::testing::Values(
        TestFunctionEntry{
            FuncKind::STRING_RPAD_NOFILL,
            "Vector{delimiter=,}: 一二三 ,二三四  ,66嘻嘻ff,二三四",
            {"Vector: 一二三 二三四 66嘻嘻ff 二三四五", "Vector: 4 5 6 3"}},
        TestFunctionEntry{FuncKind::STRING_RPAD_NOFILL,
                          "Vector{delimiter=,}: xyz ,abc  ,66ccff,NULL",
                          {"Vector: xyz abc 66ccff NULL", "Vector: 4 5 6 7"}},
        TestFunctionEntry{FuncKind::STRING_RPAD_NOFILL,
                          "Vector{delimiter=,}: xyz ,1abc,66cc,NULL",
                          {"Vector: xyz 1abc 66ccff NULL", "Scalar: 4"}},
        TestFunctionEntry{FuncKind::STRING_RPAD_NOFILL,
                          "Vector: NULL NULL NULL",
                          {"Vector: xyz abc 66ccff", "Scalar: NULL"}},
        TestFunctionEntry{FuncKind::STRING_RPAD_NOFILL,
                          "Vector{delimiter=,}: xyz,xyz1,xyz1 ,NULL",
                          {"Scalar: xyz1", "Vector: 3 4 5 NULL"}},
        TestFunctionEntry{FuncKind::STRING_RPAD_NOFILL,
                          "Vector: NULL NULL NULL",
                          {"Scalar: NULL", "Vector: 4 5 6"}}));

}  // namespace dbcommon


text:
Replicate Rails controllers, models and views like a boss.

## Installation

    $ gem install rails-graft

## Usage

From the root of your rails project.

    $ rails-graft <source> <target>

## Contributing

1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request

redpajama_set_name: RedPajamaGithub


text:
import os
from pathlib import Path
from subprocess import run

import jpype
import PyInstaller.__main__

fspath = getattr(os, 'fspath', str)

example_path = Path(__file__).parent.joinpath('example.py')

def test_start_and_stop(tmp_path):
    name = 'e'
    dist = tmp_path.joinpath('dist')
    work = tmp_path.joinpath('build')
    result = dist.joinpath(name, name)

    PyInstaller.__main__.run([
        '--name',
        name,
        '--distpath',
        fspath(dist),
        '--workpath',
        fspath(work),
        fspath(example_path),
    ])

    run([fspath(result)], check=True, cwd=fspath(tmp_path))


text:
layout: post
date: 2017-01-14
title: "Watters-Encore Encore Dress Hazel style 3223e Sleeveless Short/Mini Sheath/Column"
category: Watters-Encore
tags: [Watters-Encore,Encore,Sheath/Column,Jewel,Short/Mini,Sleeveless]
---
### Watters-Encore Encore Dress Hazel style 3223e
Just **$289.99**
###   Sleeveless Short/Mini Sheath/Column

BRANDS	Encore

Silhouette	Sheath/Column

Neckline	Jewel

Hemline/Train	Short/Mini

Sleeve	Sleeveless

Buy it: [https://www.readybrides.com/en/encore/14455-watters-dress-hazel-style-3223e.html](https://www.readybrides.com/en/encore/14455-watters-dress-hazel-style-3223e.html)


text:
import numpy as np
import regex

# - Symmetrization strategies ------------------------------------------------------------------------------------------

def sym_direct(i2o, o2i, ilen, olen):
    return i2o

def sym_inverse(i2o, o2i, ilen, olen):
    return o2i

def sym_intersect(i2o, o2i, ilen, olen):
    return sorted(set(i2o) & set(o2i))

def sym_union(i2o, o2i, ilen, olen):
    return sorted(set(i2o) | set(o2i))

def sym_grow(i2o, o2i, ilen, olen):
    union = sym_union(i2o, o2i, ilen, olen)
    alignment = sym_intersect(i2o, o2i, ilen, olen)

    new_points_added = True
    while new_points_added:
        new_points_added = False
        for i in range(ilen):
            for o in range(olen):
                if (i, o) in alignment:
                    for (i_new, o_new) in _neighboring_points_orthogonal(i, o, ilen, olen):
                        if not (_aligned_o(o_new, ilen, alignment) and _aligned_i(i_new, olen, alignment)) \
                                and ((i_new, o_new) in union):
                            alignment.append((i_new, o_new))
                            new_points_added = True

    return alignment

def sym_grow_diagonal(i2o, o2i, ilen, olen):
    union = sym_union(i2o, o2i, ilen, olen)
    alignment = sym_intersect(i2o, o2i, ilen, olen)

    new_points_added = True
    while new_points_added:
        new_points_added = False
        for i in range(ilen):
            for o in range(olen):
                if (i, o) in alignment:
                    for (i_new, o_new) in _neighboring_points_orthogonal(i, o, ilen, olen):
                        if not (_aligned_o(o_new, ilen, alignment) and _aligned_i(i_new, olen, alignment)) \
                                and ((i_new, o_new) in union):
                            alignment.append((i_new, o_new))
                            new_points_added = True

    while new_points_added:
        new_points_added = False
        for i in range(ilen):
            for o in range(olen):
                if (i, o) in alignment:
                    for (i_new, o_new) in _neighboring_points_diagonal(i, o, ilen, olen):
                        if not (_aligned_o(o_new, ilen, alignment) and _aligned_i(i_new, olen, alignment)) \
                                and ((i_new, o_new) in union):
                            alignment.append((i_new, o_new))
                            new_points_added = True

    return alignment

def sym_grow_diagonal_final_and(i2o, o2i, ilen, olen):
    alignment = sym_grow_diagonal(i2o, o2i, ilen, olen)
    _final(alignment, i2o, o2i, ilen, olen)
    return alignment

# - Make alignment -----------------------------------------------------------------------------------------------------

def make_alignment(source_indexes, target_indexes, attention_matrix, prefix_lang=None, symmetrize=sym_intersect):
    # resulting shape (layers, batch, heads, output, input);
    # last two dimensions truncated to the size of trg_sub_tokens and src_sub_tokens
    reduced_attention_matrix = attention_matrix[:len(source_indexes), :len(target_indexes)]
    alignment_matrix = reduced_attention_matrix
    norm_axis0 = (alignment_matrix / alignment_matrix.sum(axis=0)[np.newaxis])
    norm_axis1 = (alignment_matrix / alignment_matrix.sum(axis=1)[:, np.newaxis])

    s2t_best_indexes = norm_axis0.argmax(1)
    t2s_best_indexes = norm_axis1.argmax(0)

    threshold = 0.80  # TODO: find the best setting (0.85?, 0.75?, 0.90?, 1.00?)
    s_len = alignment_matrix.shape[0]
    t_len = alignment_matrix.shape[1]

    # select points of the direct alignment (having score >= threshold*best)
    t2s_sub_alignment = []
    for t in range(t_len):
        threshold_value = threshold * norm_axis1[t2s_best_indexes[t], t]
        t2s_sub_alignment += [(s, t) for s in range(s_len) if norm_axis1[s, t] >= threshold_value]

    # select points of the inverted alignment (having score >= threshold*best)
    s2t_sub_alignment = []
    for s in range(s_len):
        threshold_value = threshold * norm_axis0[s, s2t_best_indexes[s]]
        s2t_sub_alignment += [(s, t) for t in range(t_len) if norm_axis0[s, t] >= threshold_value]

    if not t2s_sub_alignment and not s2t_sub_alignment:
        return []

    # symmetrization on token-based alignment
    t2s_alignment = sorted(set([(source_indexes[al[0]], target_indexes[al[1]]) for al in t2s_sub_alignment]))
    s2t_alignment = sorted(set([(source_indexes[al[0]], target_indexes[al[1]]) for al in s2t_sub_alignment]))
    highest_source_index = source_indexes[-1]
    highest_target_index = target_indexes[-1]
    alignment = sorted(symmetrize(t2s_alignment, s2t_alignment, highest_source_index + 1, highest_target_index + 1))

    # shift source indexes if a language prefix has been used
    if prefix_lang:
        alignment = [(al[0] - 1, al[1]) for al in alignment if al[0] > 0]

    return alignment

_is_word_regex = regex.compile(r'\w', flags=regex.U)

def _is_punctuation(txt):
    return _is_word_regex.search(txt) is None

def clean_alignment(alignment, src, tgt):
    if len(alignment) == 0:
        return alignment

    filtered = []
    src_tokens = src.split()
    tgt_tokens = tgt.split()

    for align in alignment:
        src_token = src_tokens[align[0]]
        tgt_token = tgt_tokens[align[1]]

        if (_is_punctuation(src_token) and _is_punctuation(tgt_token)) or \
                (not _is_punctuation(src_token) and not _is_punctuation(tgt_token)):
            filtered.append(align)

    return filtered

# - Alignment util functions -------------------------------------------------------------------------------------------

def _neighboring_points_orthogonal(o_index, i_index, e_len, f_len):
    """
    A function that returns list of neighboring points in
    an alignment matrix for a given alignment (pair of indexes)
    """
    result = []

    if o_index > 0:
        result.append((o_index - 1, i_index))
    if i_index > 0:
        result.append((o_index, i_index - 1))
    if o_index < e_len - 1:
        result.append((o_index + 1, i_index))
    if i_index < f_len - 1:
        result.append((o_index, i_index + 1))

    return result

def _neighboring_points_diagonal(o_index, i_index, e_len, f_len):
    """
    A function that returns list of neighboring points in
    an alignment matrix for a given alignment (pair of indexes)
    """
    result = []

    if o_index > 0 and i_index > 0:
        result.append((o_index - 1, i_index - 1))
    if o_index > 0 and i_index < f_len - 1:
        result.append((o_index - 1, i_index + 1))
    if o_index < e_len - 1 and i_index > 0:
        result.append((o_index + 1, i_index - 1))
    if o_index < e_len - 1 and i_index < f_len - 1:
        result.append((o_index + 1, i_index + 1))

    return result

def _neighboring_points(o_index, i_index, e_len, f_len):
    """
    A function that returns list of neighboring points in
    an alignment matrix for a given alignment (pair of indexes)
    """
    result = []

    if o_index > 0:
        result.append((o_index - 1, i_index))
    if i_index > 0:
        result.append((o_index, i_index - 1))
    if o_index < e_len - 1:
        result.append((o_index + 1, i_index))
    if i_index < f_len - 1:
        result.append((o_index, i_index + 1))
    if o_index > 0 and i_index > 0:
        result.append((o_index - 1, i_index - 1))
    if o_index > 0 and i_index < f_len - 1:
        result.append((o_index - 1, i_index + 1))
    if o_index < e_len - 1 and i_index > 0:
        result.append((o_index + 1, i_index - 1))
    if o_index < e_len - 1 and i_index < f_len - 1:
        result.append((o_index + 1, i_index + 1))

    return result

def _aligned_o(o, ilen, alignment):
    """
    A function that checks if a given 'english' word is aligned
    to any foreign word in a given foreign sentence
    """
    for i in range(ilen):
        if (i, o) in alignment:
            return True

    return False

def _aligned_i(i, olen, alignment):
    """
    A function that checks if a given foreign word is aligned
    to any 'english' word in a given 'english' sentence
    """
    # print "i:%s" % (i)
    # print "olen:%s" % (olen)
    # print "len(alignment):%s" % (len(alignment))
    for o in range(olen):
        if (i, o) in alignment:
            return True

    return False

def _final(alignment, i2o, o2i, ilen, olen):
    """
    A function that implements both FINAL(e2f) and FINAL(f2e)
    steps of GROW-DIAG-FINAL algorithm
    """
    for o in range(olen):
        for i in range(ilen):
            if not (_aligned_o(o, ilen, alignment) and _aligned_i(i, olen, alignment)) \
                    and ((i, o) in i2o or (i, o) in o2i):
                alignment.append((i, o))


text:
title: Optimum polynomial
localeTitle: متعدد الحدود الأمثل
---
## المشكلة 101: متعدد الحدود الأمثل

هذا هو كعب. [ساعد مجتمعنا على توسيعه](https://github.com/freecodecamp/guides/tree/master/src/pages/certifications/coding-interview-prep/project-euler/problem-101-optimum-polynomial/index.md) .

[سيساعدك دليل النمط السريع هذا على ضمان قبول طلب السحب](https://github.com/freecodecamp/guides/blob/master/README.md) .


text:
package imagebuilder

const (
	// in docker/system
	NoBaseImageSpecifier = "scratch"

	// in docker/system
	defaultPathEnv = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
)


text:
package com.axway.ats.rbv.filesystem.rules;

import java.util.ArrayList;
import java.util.List;

import com.axway.ats.action.objects.FilePackage;
import com.axway.ats.action.objects.model.PackageException;
import com.axway.ats.rbv.MetaData;
import com.axway.ats.rbv.filesystem.FileSystemMetaData;
import com.axway.ats.rbv.model.RbvException;
import com.axway.ats.rbv.model.RbvStorageException;
import com.axway.ats.rbv.rules.AbstractRule;

@SuppressWarnings( "boxing")
public class FileGroupNameRule extends AbstractRule {

    private String group;

    public FileGroupNameRule( String group,
                              String ruleName,
                              boolean expectedResult ) {

        super(ruleName, expectedResult, FileSystemMetaData.class);

        //init members
        this.group = group;
    }

    public FileGroupNameRule( String atsAgent,
                              String filePath,
                              String group,
                              boolean expectedResult ) throws RbvException {

        super(group, expectedResult, FileSystemMetaData.class);

        // get source file's group
        try {
            FilePackage file = new FilePackage(atsAgent, filePath);
            this.group = file.getGroupName();
        } catch (PackageException pe) {
            throw new RbvStorageException(pe);
        }
    }

    @Override
    public boolean performMatch(
                                 MetaData metaData ) throws RbvException {

        boolean actualResult = false;

        if (metaData instanceof FileSystemMetaData) {
            //get the file from the meta data
            FilePackage file = ((FileSystemMetaData) metaData).getFilePackage();

            try {
                //get destination file's group
                String destGroup = file.getGroupName();

                // if either of the group values (expected and actual) is the NOT_SUPPORTED
                // value then we are not able to verify them and we should return true
                if (this.group == null || destGroup == null) {
                    actualResult = true;
                } else {
                    actualResult = destGroup.equals(this.group);
                }
            } catch (PackageException pe) {
                throw new RbvStorageException(pe);
            }
        }

        return actualResult;
    }

    @Override
    protected String getRuleDescription() {

        return "which expects file with Group Name " + (getExpectedResult()
                                                                            ? ""
                                                                            : "different than ")
               + "'"
               + this.group + "'";
    }

    public List<String> getMetaDataKeys() {

        List<String> metaKeys = new ArrayList<String>();
        metaKeys.add(FileSystemMetaData.FILE_PACKAGE);
        return metaKeys;
    }
}


text:
Malware Tests by Watchman Monitoring
=======

A listing of the Malware checked for by Watchman Monitoring

Support article at https://support.watchmanmonitoring.com/hc/articles/486623

For security, this document has been moved to our Subscriber Community Forum.

https://community.watchmanmonitoring.com/t/list-of-malware/1423

This is available to all subscribers.

## How does this plugin differ from true Antivirus software?

The Malware plugin in Watchman Monitoring is a lightweight test designed to locate the most common strains of Malware on the Mac platform.

It is not the intent for this simple plugin to replace a full fledged antivirus system, however in lieu of nothing, this plugin acts as a nice tool somewhere between Apple's Xprotect alone, and more aggressive antivirus product.

##How the tests work
During the agent's hourly run, the malware discovery plugin tests for the presence of key files, processes, and launchd jobs known to correspond to a known piece of malware/adware.

##Warnings versus Informational Reports
There are a number of cases where a file may be in place, but not causing issues in and of itself. There are also times when a piece of software may, or may not be "Malware". To prevent false positives, especially in cases where an average end-user may not agree there's a problem, the reporting will return as informational in the Watchman Monitoring Dashboard.

##Relative Locations
Many files will have variants in their name, or path. They are indicated by `**` below, and will have an application's name if our agent is checking through all available profiles on a computer. i.e. `*Chrome*` indicates that each profile in each home directory would be inspected.


text:
namespace CldSim
{

class Simulation
{
public:
	Simulation();
	~Simulation();

	uint GetWidth() const { return m_width; }
	uint GetHeight() const { return m_height; }
	uint GetLength() const { return m_length; }

	inline uint GetIndex(uint x, uint y, uint z) const;

	bool Setup(uint width, uint height, uint length);
	inline void InitValues();
	void Clear();
	void Restart();

	void Update(float deltaTime);

	const bool* GetCloudSpace() const { return m_cld[m_frontBufIdx]; }
	const bool* GetActiveSpace() const { return m_act[m_frontBufIdx]; }
	const bool* GetHumiditySpace() const { return m_hum[m_frontBufIdx]; }
	const float* GetExtinctionTimes() const { return m_extTimes; }

	float GetHumidityProbability() const { return m_pHumUpdate; }
	void SetHumidityProbability(float value) { m_pHumUpdate = value; }

	float GetActiveProbability() const { return m_pActUpdate; }
	void SetActiveProbability(float value) { m_pActUpdate = value; }

	float GetExtinctionProbability() const { return m_pExtUpdate; }
	void SetExtinctionProbability(float value) { m_pExtUpdate = value; }

	float GetExtinctionTime() const { return m_tExt; }
	void SetExtinctionTime(float value) { m_tExt = value; }

private:
	uint m_width; //x
	uint m_height; //y
	uint m_length; //z

	uint m_elapsedSteps;
	uint m_frontBufIdx;
	uint m_backBufIdx;

	bool* m_hum[2];//TODO: optimize to bit field?
	bool* m_act[2];
	bool* m_cld[2];
	bool* m_ext[2];
	float* m_extTimes;

	float m_pHumInit = 0.2f;
	float m_pActInit = 0.2f;

	float m_tExt = 2.0f;

	float m_pHumUpdate = 0.01f;
	float m_pActUpdate = 0.1f;
	float m_pExtUpdate = 0.995f;

	bool IsCellInSpace(uint x, uint y, uint z) const;

	inline void Simulate(uint x, uint y, uint z, float deltaTime);

	bool CalcNeighborFunc(bool* space, uint x, uint y, uint z) const;
};

}


text:
import { expect } from 'chai';
import getAuthReducer, {
  getFreshLoginReducer,
  getLoginStatusReducer,
  getProxyLoadedReducer,
  getProxyRetryCountReducer,
  getOwnerIdReducer,
  getEndpointIdReducer,
} from './getAuthReducer';
import getModuleStatusReducer from '../../lib/getModuleStatusReducer';

import actionTypes from './actionTypes';
import loginStatus from './loginStatus';

describe('getLoginStatusReducer', () => {
  it('should be a function', () => {
    expect(getLoginStatusReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getLoginStatusReducer(actionTypes)).to.be.a('function');
  });
  describe('loginStatusReducer', () => {
    const reducer = getLoginStatusReducer(actionTypes);
    it('should have initial state of null', () => {
      expect(reducer(undefined, {})).to.equal(null);
    });
    it('should return original state of actionTypes is not recognized', () => {
      const originalState = {};
      expect(reducer(originalState, { type: 'foo' }))
        .to.equal(originalState);
    });
    describe('actionTypes => loginStatus', () => {
      it('actionTypes.login => loginStatus.loggingIn', () => {
        expect(reducer(null, {
          type: actionTypes.login,
        })).to.equal(loginStatus.loggingIn);
      });
      it('actionTypes.loginSuccess => loginStatus.loggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.loginSuccess,
        })).to.equal(loginStatus.loggedIn);
      });
      it('actionTypes.refreshSuccess => loginStatus.loggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.refreshSuccess,
        })).to.equal(loginStatus.loggedIn);
      });
      it('actionTypes.cancelLogout => loginStatus.loggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.cancelLogout,
        })).to.equal(loginStatus.loggedIn);
      });
      it('actionTypes.loginError => loginStatus.notLoggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.loginError,
        })).to.equal(loginStatus.notLoggedIn);
      });
      it('actionTypes.logoutSuccess => loginStatus.notLoggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.logoutSuccess,
        })).to.equal(loginStatus.notLoggedIn);
      });
      it('actionTypes.logoutError => loginStatus.notLoggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.logoutError,
        })).to.equal(loginStatus.notLoggedIn);
      });
      it('actionTypes.refreshError => refreshTokenValid ? state : loginStatus.notLoggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.refreshError,
          refreshTokenValid: false,
        })).to.equal(loginStatus.notLoggedIn);
        expect(reducer(loginStatus.loggedIn, {
          type: actionTypes.refreshError,
          refreshTokenValid: true,
        })).to.equal(loginStatus.loggedIn);
      });
      it('actionTypes.logout => loginStatus.loggingOut', () => {
        expect(reducer(null, {
          type: actionTypes.logout,
        })).to.equal(loginStatus.loggingOut);
      });
      it('actionTypes.beforeLogout => loginStatus.beforeLogout', () => {
        expect(reducer(null, {
          type: actionTypes.beforeLogout,
        })).to.equal(loginStatus.beforeLogout);
      });
      it('actionTypes.refresh => originalState', () => {
        const originalState = {};
        expect(reducer(originalState, {
          type: actionTypes.refresh,
        })).to.equal(originalState);
      });
      it('actionTypes.init => state', () => {
        expect(reducer('originalState', {
          type: actionTypes.init,
        })).to.equal('originalState');
      });
      it('actionTypes.initSuccess && !loggedIn => loginStatus.notLoggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.initSuccess,
          loggedIn: false,
        })).to.equal(loginStatus.notLoggedIn);
      });
      it('actionTypes.initSuccess && loggedIn => loginStatus.loggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.initSuccess,
          loggedIn: true,
        })).to.equal(loginStatus.loggedIn);
      });
      it('actionTypes.tabSync && !loggedIn => loginStatus.notLoggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.tabSync,
          loggedIn: false,
        })).to.equal(loginStatus.notLoggedIn);
      });
      it('actionTypes.tabSync && loggedIn => loginStatus.loggedIn', () => {
        expect(reducer(null, {
          type: actionTypes.tabSync,
          loggedIn: true,
        })).to.equal(loginStatus.loggedIn);
      });
    });
  });
});

describe('getOwnerIdReducer', () => {
  it('should be a function', () => {
    expect(getOwnerIdReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getOwnerIdReducer(actionTypes)).to.be.a('function');
  });
  describe('ownerIdReducer', () => {
    const reducer = getOwnerIdReducer(actionTypes);
    it('should have initial state of null', () => {
      expect(reducer(undefined, {})).to.be.null;
    });
    it('should return original state of actionTypes is not recognized', () => {
      const originalState = {};
      expect(reducer(originalState, { type: 'foo' }))
        .to.equal(originalState);
    });
    it('should return ownerId on loginSuccess', () => {
      expect(reducer(null, {
        type: actionTypes.loginSuccess,
        token: {
          owner_id: 'foo',
        },
      })).to.equal('foo');
    });
    it('should return ownerId on refreshSuccess', () => {
      expect(reducer(null, {
        type: actionTypes.refreshSuccess,
        token: {
          owner_id: 'foo',
        },
      })).to.equal('foo');
    });
    it('should return null on following auth action types', () => {
      [
        actionTypes.loginError,
        actionTypes.logoutSuccess,
        actionTypes.logoutError,
        actionTypes.refreshError,
      ].forEach(type => {
        expect(reducer('foo', {
          type,
        })).to.be.null;
      });
    });
    it('should ignore other auth action types', () => {
      const originalState = {};
      [
        actionTypes.login,
        actionTypes.logout,
        actionTypes.refresh,
        actionTypes.beforeLogout,
        actionTypes.cancelLogout,
      ].forEach(type => {
        expect(reducer(originalState, {
          type,
        })).to.equal(originalState);
      });
    });
    it('should return ownerId on initSuccess with token', () => {
      expect(reducer(null, {
        type: actionTypes.initSuccess,
        token: {
          owner_id: 'foo',
        },
      })).to.equal('foo');
    });
    it('should return null on initSuccess without token', () => {
      expect(reducer('foo', {
        type: actionTypes.initSuccess,
      })).to.be.null;
    });
    it('should return ownerId on tabSync with token', () => {
      expect(reducer(null, {
        type: actionTypes.tabSync,
        token: {
          owner_id: 'foo',
        },
      })).to.equal('foo');
    });
    it('should return null on tabSync without token', () => {
      expect(reducer('foo', {
        type: actionTypes.tabSync,
      })).to.be.null;
    });
  });
});

describe('getEndpointIdReducer', () => {
  it('should be a function', () => {
    expect(getEndpointIdReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getEndpointIdReducer(actionTypes)).to.be.a('function');
  });
  describe('endpointIdReducer', () => {
    const reducer = getEndpointIdReducer(actionTypes);
    it('should have initial state of null', () => {
      expect(reducer(undefined, {})).to.be.null;
    });
    it('should return original state of actionTypes is not recognized', () => {
      const originalState = {};
      expect(reducer(originalState, { type: 'foo' }))
        .to.equal(originalState);
    });
    it('should return endpoint_id on loginSuccess', () => {
      expect(reducer(null, {
        type: actionTypes.loginSuccess,
        token: {
          endpoint_id: 'foo',
        },
      })).to.equal('foo');
    });
    it('should return endpoint_id on refreshSuccess', () => {
      expect(reducer(null, {
        type: actionTypes.refreshSuccess,
        token: {
          endpoint_id: 'foo',
        },
      })).to.equal('foo');
    });
    it('should return null on following auth action types', () => {
      [
        actionTypes.loginError,
        actionTypes.logoutSuccess,
        actionTypes.logoutError,
      ].forEach((type) => {
        expect(reducer('foo', {
          type,
        })).to.be.null;
      });
    });

    it('should return null on refreshError and refreshToken not Valid', () => {
      expect(reducer(null, {
        type: actionTypes.refreshError,
        token: {
          endpoint_id: 'foo',
        },
        refreshTokenValid: false,
      })).to.equal(null);
    });

    it('should return original state on refreshError and refreshToken Valid', () => {
      const originalState = {};
      expect(reducer(originalState, {
        type: actionTypes.refreshError,
        token: {
          endpoint_id: 'foo',
        },
        refreshTokenValid: true,
      })).to.equal(originalState);
    });

    it('should ignore other auth action types', () => {
      const originalState = {};
      [
        actionTypes.login,
        actionTypes.logout,
        actionTypes.refresh,
        actionTypes.beforeLogout,
        actionTypes.cancelLogout,
      ].forEach((type) => {
        expect(reducer(originalState, {
          type,
        })).to.equal(originalState);
      });
    });

    it('should return endpoint_id on initSuccess with token', () => {
      expect(reducer(null, {
        type: actionTypes.initSuccess,
        token: {
          endpoint_id: 'foo',
        },
      })).to.equal('foo');
    });

    it('should return null on initSuccess without token', () => {
      expect(reducer('foo', {
        type: actionTypes.initSuccess,
      })).to.be.null;
    });

    it('should return endpoint_id on tabSync with token', () => {
      expect(reducer(null, {
        type: actionTypes.tabSync,
        token: {
          endpoint_id: 'foo',
        },
      })).to.equal('foo');
    });

    it('should return null on tabSync without token', () => {
      expect(reducer('foo', {
        type: actionTypes.tabSync,
      })).to.be.null;
    });
  });
});

describe('getFreshLoginReducer', () => {
  it('should be a function', () => {
    expect(getFreshLoginReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getFreshLoginReducer(actionTypes)).to.be.a('function');
  });
  describe('freshLoginReducer', () => {
    const reducer = getFreshLoginReducer(actionTypes);
    it('should have initial state of null', () => {
      expect(reducer(undefined, {})).to.be.null;
    });
    it('should return original state of actionTypes is not recognized', () => {
      const originalState = {};
      expect(reducer(originalState, { type: 'foo' }))
        .to.equal(originalState);
    });
    it('should return true on login action type', () => {
      expect(reducer(null, {
        type: actionTypes.login,
      })).to.be.true;
    });
    it('should return null on following auth action types', () => {
      [
        actionTypes.loginError,
        actionTypes.logoutError,
        actionTypes.refreshError,
        actionTypes.logoutSuccess,
      ].forEach(type => {
        expect(reducer('foo', {
          type,
        })).to.equal(null);
      });
    });
    it('should ignore the following auth action types', () => {
      const originalState = {};
      [
        actionTypes.cancelLogout,
        actionTypes.loginSuccess,
        actionTypes.logout,
        actionTypes.refresh,
        actionTypes.refreshSuccess,
        actionTypes.beforeLogout,
        actionTypes.init,
      ].forEach(type => {
        expect(reducer(originalState, {
          type,
        })).to.equal(originalState);
      });
    });
    it('should return false on authActionType.initSuccess && loggedIn', () => {
      expect(reducer(null, {
        type: actionTypes.initSuccess,
        loggedIn: true,
      })).to.be.false;
    });
    it('should return null on authActionType.initSuccess && !loggedIn', () => {
      expect(reducer(null, {
        type: actionTypes.initSuccess,
        loggedIn: false,
      })).to.be.null;
    });
    it('should return false on authActionType.tabSync && loggedIn', () => {
      expect(reducer(null, {
        type: actionTypes.tabSync,
        loggedIn: true,
      })).to.be.false;
    });
    it('should return null on authActionType.tabSync && !loggedIn', () => {
      expect(reducer(null, {
        type: actionTypes.tabSync,
        loggedIn: false,
      })).to.be.null;
    });
  });
});

describe('getProxyLoadedReducer', () => {
  it('should be a function', () => {
    expect(getProxyLoadedReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getProxyLoadedReducer(actionTypes)).to.be.a('function');
  });
  describe('proxyLoadedReducer', () => {
    const reducer = getProxyLoadedReducer(actionTypes);
    it('should have initial state of false', () => {
      expect(reducer(undefined, {})).to.be.false;
    });
    it('should return original state of actionTypes is not recognized', () => {
      const originalState = {};
      expect(reducer(originalState, { type: 'foo' }))
        .to.equal(originalState);
    });
    it('should return true on proxyLoaded', () => {
      expect(reducer('foo', {
        type: actionTypes.proxyLoaded,
      })).to.be.true;
    });
    it('should return false on proxyCleared', () => {
      expect(reducer('foo', {
        type: actionTypes.proxyCleared,
      })).to.be.false;
    });
  });
});

describe('getProxyRetryCountReducer', () => {
  it('should be a function', () => {
    expect(getProxyRetryCountReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getProxyRetryCountReducer(actionTypes)).to.be.a('function');
  });
  describe('proxyTimestampReducer', () => {
    const reducer = getProxyRetryCountReducer(actionTypes);
    it('should have initial state of 0', () => {
      expect(reducer(undefined, {})).to.equal(0);
    });
    it('should return original state of actionTypes is not recognized', () => {
      const originalState = {};
      expect(reducer(originalState, { type: 'foo' }))
        .to.equal(originalState);
    });
    it('should return 0 on proxySetup, proxyCleared and proxyLoaded', () => {
      expect(reducer('foo', {
        type: actionTypes.proxySetup,
      })).to.equal(0);
      expect(reducer('foo', {
        type: actionTypes.proxyCleared,
      })).to.equal(0);
      expect(reducer('foo', {
        type: actionTypes.proxyLoaded,
      })).to.equal(0);
    });
    it('should return state + 1 on proxyRetry', () => {
      expect(reducer(0, {
        type: actionTypes.proxyRetry,
      })).to.equal(1);
    });
  });
});

describe('getAuthReducer', () => {
  it('should be a function', () => {
    expect(getAuthReducer).to.be.a('function');
  });
  it('should return a reducer', () => {
    expect(getAuthReducer()).to.be.a('function');
  });
  describe('authReducer', () => {
    const reducer = getAuthReducer(actionTypes);
    const statusReducer = getModuleStatusReducer(actionTypes);
    const loginStatusReducer = getLoginStatusReducer(actionTypes);
    const freshLoginReducer = getFreshLoginReducer(actionTypes);
    const ownerIdReducer = getOwnerIdReducer(actionTypes);
    const proxyLoadedReducer = getProxyLoadedReducer(actionTypes);
    const proxyRetryCountReducer = getProxyRetryCountReducer(actionTypes);
    const endpointIdReducer = getEndpointIdReducer(actionTypes);
    it('should return combined state', () => {
      expect(reducer(undefined, {}))
        .to.deep.equal({
          status: statusReducer(undefined, {}),
          loginStatus: loginStatusReducer(undefined, {}),
          freshLogin: freshLoginReducer(undefined, {}),
          ownerId: ownerIdReducer(undefined, {}),
          proxyLoaded: proxyLoadedReducer(undefined, {}),
          proxyRetryCount: proxyRetryCountReducer(undefined, {}),
          endpointId: endpointIdReducer(undefined, {}),
        });
      const error = new Error('test');
      const token = {
        owner_id: 'foo',
        endpoint_id: 'foo',
      };
      [
        {
          type: actionTypes.login,
        },
        {
          type: actionTypes.loginSuccess,
          token,
        },
        {
          type: actionTypes.loginError,
          error,
        },
        {
          type: actionTypes.logout,
        },
        {
          type: actionTypes.logoutSuccess,
        },
        {
          type: actionTypes.logoutError,
          error,
        },
        {
          type: actionTypes.refresh,
        },
        {
          type: actionTypes.refreshSuccess,
          token,
        },
        {
          type: actionTypes.refreshError,
          error,
        },
        {
          type: actionTypes.beforeLogout,
        },
        {
          type: actionTypes.cancelLogout,
          error,
        },
        {
          type: actionTypes.init,
        },
        {
          type: actionTypes.initSuccess,
          loggedIn: true,
          token,
        },
        {
          type: actionTypes.initSuccess,
          loggedIn: false,
        },
        {
          type: actionTypes.tabSync,
          loggedIn: true,
          token,
        },
        {
          type: actionTypes.tabSync,
          loggedIn: false,
        },
      ].forEach((action) => {
        expect(reducer({
          status: 'status',
          loginStatus: 'loginStatus',
          freshLogin: 'freshLogin',
          ownerId: 'ownerId',
          endpointId: 'endpointId',
          proxyLoaded: false,
        }, action)).to.deep.equal({
          status: statusReducer('status', action),
          loginStatus: loginStatusReducer('loginStatus', action),
          freshLogin: freshLoginReducer('freshLogin', action),
          ownerId: ownerIdReducer('ownerId', action),
          endpointId: endpointIdReducer('endpointId', action),
          proxyLoaded: proxyLoadedReducer(false, action),
          proxyRetryCount: proxyRetryCountReducer(undefined, {}),
        });
      });
    });
  });
});


text:
<!DOCTYPE html>

    <title></title>

Description:

This example demonstrates how to parse a number using an implied, but exact, pattern based on the language settings.  An application using this method to parse a number can automatically assume that the pattern for that type of number will be applied based on the user's formatting preferences.  An application can also choose to override the user's preferences and specify the settings to use for a given parse operation.

This example demonstrates how to parse a number as a currency, percent or decimal. The results displayed below show each of these types using the current user's preferences as well as two example forms.

            <button id="displayButton">Display</button>