text:
namespace _05.Define64BitArr
{
    using System;
    using System.Collections;

    public class BitArray64Enum : IEnumerator
    {
        private ulong[] array;
        private int position = -1;

        public BitArray64Enum(ulong[] arr)
        {
            this.array = arr;
        }

        public object Current
        {
            get
            {
                try
                {
                    return this.array[position];
                }
                catch (IndexOutOfRangeException)
                {
                    throw new InvalidOperationException();
                }
            }
        }

        public bool MoveNext()
        {
            this.position++;
            if (position < this.array.Length)
            {
                return true;
            }
            return false;
        }

        public void Reset()
        {
            this.position = -1;
        }
    }
}


text:
using RevisionManager;
using System.Runtime.InteropServices;

internal static class Example
{

    public static void Main()
    {
        SolidEdgeFileProperties.PropertySets objPropertySets = null;
        SolidEdgeFileProperties.Properties objProperties = null;
        SolidEdgeFileProperties.Property objProperty = null;

        try
        {
            // Create a new instance of PropertySets.
            objPropertySets = new SolidEdgeFileProperties.PropertySets();
            objPropertySets.Open("C:\\Part1.par", false);
            objProperties = objPropertySets.Item("Custom");
            objProperty = objProperties.Add("My Custom Property", "My Custom Value");
            objProperty.Delete();
            objPropertySets.Save();
            objPropertySets.Close();
        }
        catch (Exception ex)
        {
            // Write any errors to console.
            Console.WriteLine(ex.Message);
        }
        finally
        {
            // Release COM Objects.
            if (objProperties != null)
            {
                Marshal.ReleaseComObject(objProperties);
                objProperties = null;
            }
            if (objPropertySets != null)
            {
                Marshal.ReleaseComObject(objPropertySets);
                objPropertySets = null;
            }
        }
    }

}

redpajama_set_name: RedPajamaGithub


text:
module Spec
  module Rails
    module Matchers
      class HTMLElementMatcher
        def initialize(spec_scope, tag_name, *args)
          @attributes = args.extract_options!
          @tag_name = tag_name
          @spec_scope = spec_scope

          @tag = [@tag_name, extract_id, extract_classes, build_attributes].compact.join
          @matcher = spec_scope.send(:have_tag, @tag, *args)
        end

        def matches?(response)
          @matcher.matches?(response)
        end

        [:failure_message, :negative_failure_message, :description].each do |method|
          define_method(method) { @matcher.send(method) }
        end

      private

        def extract_id
          "##{@attributes.delete(:id)}" if @attributes[:id]
        end

        def extract_classes
          classes = case css = @attributes.delete(:class)
          when String
            css.split(' ')
          when Array
            css
          end
          '.' + classes.join('.') if classes
        end

        def build_attributes
          @attributes.collect {|attr,value| "[#{attr}='#{value}']" }.join
        end
      end

      def have_form_getting_from(url_or_path)
        return simple_matcher("have a form submitting via GET to '#{url_or_path}'") do
          have_tag("form[method=get][action=#{url_or_path}]").matches?(response)
        end
      end

      def have_form_posting_to(url_or_path)
        return simple_matcher("have a form submitting via POST to '#{url_or_path}'") do |response|
          have_tag("form[method=post][action=#{url_or_path}]").matches?(response)
        end
      end

      def have_form_putting_to(url_or_path)
        return simple_matcher("have a form submitting via PUT to '#{url_or_path}'") do |response|
          have_tag("form[method=post][action=#{url_or_path}]").matches?(response)
          have_tag("input[name=_method][type=hidden][value=put]").matches?(response)
        end
      end

      def have_label_for(model, attribute, text = nil)
        HTMLElementMatcher.new(self, 'label', text, :for => "#{model}_#{attribute}")
      end
      alias_method :with_label_for, :have_label_for

      def have_text_area_for(model, attribute)
        HTMLElementMatcher.new(self, 'textarea',
          :id => "#{model}_#{attribute}",
          :name => "#{model}[#{attribute}]")
      end
      alias_method :with_text_area_for, :have_text_area_for

      %w(text password checkbox file).each do |input|
        define_method("have_#{input}_field_for") do |model, attribute|
          HTMLElementMatcher.new(self, 'input',
            :type => input,
            :id => "#{model}_#{attribute}",
            :name => "#{model}[#{attribute}]")
        end
        alias_method :"with_#{input}_field_for", :"have_#{input}_field_for"
      end

      def have_submit_button(options = {})
        HTMLElementMatcher.new(self, 'input', options.merge(:type => 'submit'))
      end
      alias_method :with_submit_button, :have_submit_button

      def have_link_to(url_or_path, text = nil)
        return simple_matcher("have a link to '#{url_or_path}'") do |response|
          have_tag("a[href=#{url_or_path}]", text).matches?(response)
        end
      end
      alias_method :with_link_to, :have_link_to

      def content_for(name)
        response.template.instance_variable_get("@content_for_#{name}")
      end
    end
  end
end


text:
package com.htmlhifive.pitalium.it.screenshot_old.partialapge;

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

import com.htmlhifive.pitalium.core.config.PtlTestConfig;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

import com.htmlhifive.pitalium.common.exception.TestRuntimeException;
import com.htmlhifive.pitalium.core.PtlTestBase;
import com.htmlhifive.pitalium.core.model.CompareTarget;
import com.htmlhifive.pitalium.core.model.ScreenArea;
import com.htmlhifive.pitalium.core.model.SelectorType;

/**
 * スクリーンショット取得時に、複数回同じIDを指定した場合のテスト
 */
public class TakeWithDuplicateIdTest extends PtlTestBase {

	private static final String BASE_URL = PtlTestConfig.getInstance().getTestAppConfig().getBaseUrl();

	/**
	 * 同じIDを指定して複数のスクリーンショットを取得しようとした場合に例外が発生することを確認する。

	 * 実行環境:IE7~11/FireFox/Chrome/Android 2.3, 4.0, 4.4/iOS 8.1

	 * 期待結果:例外が発生する
	 */

	@Rule
	public ExpectedException thrown = ExpectedException.none();

	@Test
	public void takeWithDuplicateId() {
		driver.get(BASE_URL);
		List<CompareTarget> targets = new ArrayList<CompareTarget>();
		targets.add(new CompareTarget(ScreenArea.of(SelectorType.CSS_SELECTOR, "#about")));
		assertionView.assertView("Overlapping", targets);

		targets.clear();
		targets.add(new CompareTarget(ScreenArea.of(SelectorType.CSS_SELECTOR, "#news")));
		thrown.expect(TestRuntimeException.class);
		assertionView.assertView("Overlapping", targets);

	}
}


text:
[Official repository][repo].

[repo]: https://index.docker.io/u/thoughtpolice/rethinkdb/

# Quick Start

To start a server:

```
$ docker pull thoughtpolice/rethinkdb
$ RETHINKDB_MASTER=$(docker run -d thoughtpolice/rethinkdb)
$ RETHINKDB_MASTER_IP=$(docker inspect $RETHINKDB_MASTER | grep IPAddress | awk '{ print $2 }' | tr -d ',"')
```

You can now view the web interface at `$RETHINKDB_MASTER_IP:8080`.

You can connect more nodes as slaves:

```
$ docker run -d thoughtpolice/rethinkdb rethinkdb --join $RETHINKDB_MASTER_IP:29015
```

All of the RethinkDB nodes have their data located in
`/data/rethinkdb_data` by default, so you can map this directory
however you want to the host.


text:
using namespace TPath;

class NavigationMesh{
public:
    NavigationMesh();
    ~NavigationMesh();
    void Draw(Canvas &c, const int cam_x,const int cam_y,const float zoom);
    bool Extrude(const int Line_Start_Id,const TMath::Point new_pos2,const TMath::Point new_pos1);
    void Extrude(const int Point_Start_Id,const TMath::Point new_pos);
    bool ExtrudeMerge(const int Line_Start_Id,const int snap_to_edge);
    void Input(const clan::InputEvent &e,const int cam_x,const int cam_y, const float zoom);
    std::vector<NavSaveLoadPoint> points;
    std::vector<NavSaveLoadEdge> edges;
    std::vector<NavSaveLoadTriangle> quads;
    TMath::Point placment_point_a = TMath::Point(-100,-100);
    TMath::Point placment_point_b = TMath::Point(-100,-100);
    std::vector<TMath::Point> placment_points_a;
    std::vector<TMath::Point> placment_points_b;
    std::vector<TMath::Point> placment_points;
    std::vector<int> edges_selected;
    std::vector<int> points_selected;
    bool is_point_selected = false;
    bool Selection(const clan::InputEvent &e,const int cam_x,const int cam_y, const float zoom);
    bool SelectionEdge(const clan::InputEvent &e,const int cam_x,const int cam_y, const float zoom);
    bool is_extruding = false;
    bool GetShortestTwoLines(const TMath::Point point_a,const TMath::Point point_b,const TMath::Point point_c,const TMath::Point point_d);
    void MakeFace(const int edge1,const int edge2,const int edge3);
    void MakeEdge(const int point_1,const int point_2);
    void EraseEdge(const int i);
    void ErasePoint(const int i);
    void Save(clan::File &file);
    void LoadFrom(TPath::NavSaveLoadData &data);
    void GeneratePiece();
    void MovedPiece(int i);
    void CircleSelect(const int cam_x,const int cam_y, const float zoom);
    Rectf GenerateBoundery();
    Rectf MirrorX(Rectf map_rect);
    void RemoveDoubles();
    Vec2f CursorLoc;
    bool circle_select = false;
    int circle_select_radius = 10;
};


text:
import os

from flask import Flask

from .auth import auth, login_manager
from .database import db_session
from .views import views

def create_app():
    app = Flask(__name__)
    app.secret_key = os.getenv("SECRET_KEY")
    app.register_blueprint(auth)
    app.register_blueprint(views)
    login_manager.init_app(app)
    return app

# Exposing so can be picked up by Zappa
app = create_app()

@app.teardown_appcontext
def shutdown_session(exception=None):
    db_session.remove()

if __name__ == "__main__":
    import sys

    app = create_app()
    try:
        port = int(sys.argv[1])
    except (IndexError, ValueError):
        port = 5000
    app.run(debug=True, port=port)


text:
namespace Server.Admin.Models
{
    using Server.Framework.Entities;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    public class PagedModel<T>
    {
        public IEnumerable<T> Items { get; set; }

        public int ItemsTotal { get; set; }
    }
}


text:
package org.apache.spark.sql.catalyst.expressions

import java.math.{BigDecimal => JavaBigDecimal}

import org.apache.spark.SparkFunSuite
import org.apache.spark.sql.catalyst.analysis.TypeCheckResult
import org.apache.spark.sql.catalyst.dsl.expressions._
import org.apache.spark.sql.catalyst.expressions.codegen.GenerateUnsafeProjection
import org.apache.spark.sql.internal.SQLConf
import org.apache.spark.sql.types._

class StringExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper {

  test("concat") {
    def testConcat(inputs: String*): Unit = {
      val expected = if (inputs.contains(null)) null else inputs.mkString
      checkEvaluation(Concat(inputs.map(Literal.create(_, StringType))), expected)
    }

    testConcat()
    testConcat(null)
    testConcat("")
    testConcat("ab")
    testConcat("a", "b")
    testConcat("a", "b", "C")
    testConcat("a", null, "C")
    testConcat("a", null, null)
    testConcat(null, null, null)

    // scalastyle:off
    // non ascii characters are not allowed in the code, so we disable the scalastyle here.
    testConcat("数据", null, "砖头")
    // scalastyle:on
  }

  test("SPARK-22498: Concat should not generate codes beyond 64KB") {
    val N = 5000
    val strs = (1 to N).map(x => s"s$x")
    checkEvaluation(Concat(strs.map(Literal.create(_, StringType))), strs.mkString)
  }

  test("SPARK-22771 Check Concat.checkInputDataTypes results") {
    assert(Concat(Seq.empty[Expression]).checkInputDataTypes().isSuccess)
    assert(Concat(Literal.create("a") :: Literal.create("b") :: Nil)
      .checkInputDataTypes().isSuccess)
    assert(Concat(Literal.create("a".getBytes) :: Literal.create("b".getBytes) :: Nil)
      .checkInputDataTypes().isSuccess)
    assert(Concat(Literal.create(1) :: Literal.create(2) :: Nil)
      .checkInputDataTypes().isFailure)
    assert(Concat(Literal.create("a") :: Literal.create("b".getBytes) :: Nil)
      .checkInputDataTypes().isFailure)
  }

  test("concat_ws") {
    def testConcatWs(expected: String, sep: String, inputs: Any*): Unit = {
      val inputExprs = inputs.map {
        case s: Seq[_] => Literal.create(s, ArrayType(StringType))
        case null => Literal.create(null, StringType)
        case s: String => Literal.create(s, StringType)
      }
      val sepExpr = Literal.create(sep, StringType)
      checkEvaluation(ConcatWs(sepExpr +: inputExprs), expected)
    }

    // scalastyle:off
    // non ascii characters are not allowed in the code, so we disable the scalastyle here.
    testConcatWs(null, null)
    testConcatWs(null, null, "a", "b")
    testConcatWs("", "")
    testConcatWs("ab", "哈哈", "ab")
    testConcatWs("a哈哈b", "哈哈", "a", "b")
    testConcatWs("a哈哈b", "哈哈", "a", null, "b")
    testConcatWs("a哈哈b哈哈c", "哈哈", null, "a", null, "b", "c")

    testConcatWs("ab", "哈哈", Seq("ab"))
    testConcatWs("a哈哈b", "哈哈", Seq("a", "b"))
    testConcatWs("a哈哈b哈哈c哈哈d", "哈哈", Seq("a", null, "b"), null, "c", Seq(null, "d"))
    testConcatWs("a哈哈b哈哈c", "哈哈", Seq("a", null, "b"), null, "c", Seq.empty[String])
    testConcatWs("a哈哈b哈哈c", "哈哈", Seq("a", null, "b"), null, "c", Seq[String](null))
    // scalastyle:on
  }

  test("SPARK-22549: ConcatWs should not generate codes beyond 64KB") {
    val N = 5000
    val sepExpr = Literal.create("#", StringType)
    val strings1 = (1 to N).map(x => s"s$x")
    val inputsExpr1 = strings1.map(Literal.create(_, StringType))
    checkEvaluation(ConcatWs(sepExpr +: inputsExpr1), strings1.mkString("#"))

    val strings2 = (1 to N).map(x => Seq(s"s$x"))
    val inputsExpr2 = strings2.map(Literal.create(_, ArrayType(StringType)))
    checkEvaluation(
      ConcatWs(sepExpr +: inputsExpr2), strings2.map(s => s(0)).mkString("#"))
  }

  test("elt") {
    def testElt(result: String, n: java.lang.Integer, args: String*): Unit = {
      checkEvaluation(
        Elt(Literal.create(n, IntegerType) +: args.map(Literal.create(_, StringType))),
        result)
    }

    testElt("hello", 1, "hello", "world")
    testElt(null, 1, null, "world")
    testElt(null, null, "hello", "world")

    // Invalid ranges
    withSQLConf(SQLConf.ANSI_ENABLED.key -> "false") {
      // ANSI will throw SparkArrayIndexOutOfBoundsException with invalid index
      testElt(null, 3, "hello", "world")
      testElt(null, 0, "hello", "world")
      testElt(null, -1, "hello", "world")
    }

    // type checking
    assert(Elt(Seq.empty).checkInputDataTypes().isFailure)
    assert(Elt(Seq(Literal(1))).checkInputDataTypes().isFailure)
    assert(Elt(Seq(Literal(1), Literal("A"))).checkInputDataTypes().isSuccess)
    assert(Elt(Seq(Literal(1), Literal(2))).checkInputDataTypes().isFailure)
  }

  test("SPARK-22550: Elt should not generate codes beyond 64KB") {
    val N = 10000
    val strings = (1 to N).map(x => s"s$x")
    val args = Literal.create(N, IntegerType) +: strings.map(Literal.create(_, StringType))
    checkEvaluation(Elt(args), s"s$N")
  }

  test("StringComparison") {
    val row = create_row("abc", null)
    val c1 = $"a".string.at(0)
    val c2 = $"a".string.at(1)

    checkEvaluation(c1 contains "b", true, row)
    checkEvaluation(c1 contains "x", false, row)
    checkEvaluation(c2 contains "b", null, row)
    checkEvaluation(c1 contains Literal.create(null, StringType), null, row)

    checkEvaluation(c1 startsWith "a", true, row)
    checkEvaluation(c1 startsWith "b", false, row)
    checkEvaluation(c2 startsWith "a", null, row)
    checkEvaluation(c1 startsWith Literal.create(null, StringType), null, row)

    checkEvaluation(c1 endsWith "c", true, row)
    checkEvaluation(c1 endsWith "b", false, row)
    checkEvaluation(c2 endsWith "b", null, row)
    checkEvaluation(c1 endsWith Literal.create(null, StringType), null, row)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(Contains(Literal("\"quote"), Literal("\"quote")) :: Nil)
    GenerateUnsafeProjection.generate(EndsWith(Literal("\"quote"), Literal("\"quote")) :: Nil)
    GenerateUnsafeProjection.generate(StartsWith(Literal("\"quote"), Literal("\"quote")) :: Nil)
  }

  test("Substring") {
    val row = create_row("example", "example".toArray.map(_.toByte))

    val s = $"a".string.at(0)

    // substring from zero position with less-than-full length
    checkEvaluation(
      Substring(s, Literal.create(0, IntegerType), Literal.create(2, IntegerType)), "ex", row)
    checkEvaluation(
      Substring(s, Literal.create(1, IntegerType), Literal.create(2, IntegerType)), "ex", row)

    // substring from zero position with full length
    checkEvaluation(
      Substring(s, Literal.create(0, IntegerType), Literal.create(7, IntegerType)), "example", row)
    checkEvaluation(
      Substring(s, Literal.create(1, IntegerType), Literal.create(7, IntegerType)), "example", row)

    // substring from zero position with greater-than-full length
    checkEvaluation(Substring(s, Literal.create(0, IntegerType), Literal.create(100, IntegerType)),
      "example", row)
    checkEvaluation(Substring(s, Literal.create(1, IntegerType), Literal.create(100, IntegerType)),
      "example", row)

    // substring from nonzero position with less-than-full length
    checkEvaluation(Substring(s, Literal.create(2, IntegerType), Literal.create(2, IntegerType)),
      "xa", row)

    // substring from nonzero position with full length
    checkEvaluation(Substring(s, Literal.create(2, IntegerType), Literal.create(6, IntegerType)),
      "xample", row)

    // substring from nonzero position with greater-than-full length
    checkEvaluation(Substring(s, Literal.create(2, IntegerType), Literal.create(100, IntegerType)),
      "xample", row)

    // zero-length substring (within string bounds)
    checkEvaluation(Substring(s, Literal.create(0, IntegerType), Literal.create(0, IntegerType)),
      "", row)

    // zero-length substring (beyond string bounds)
    checkEvaluation(Substring(s, Literal.create(100, IntegerType), Literal.create(4, IntegerType)),
      "", row)

    // substring(null, _, _) -> null
    checkEvaluation(Substring(s, Literal.create(100, IntegerType), Literal.create(4, IntegerType)),
      null, create_row(null))

    // substring(_, null, _) -> null
    checkEvaluation(Substring(s, Literal.create(null, IntegerType), Literal.create(4, IntegerType)),
      null, row)

    // substring(_, _, null) -> null
    checkEvaluation(
      Substring(s, Literal.create(100, IntegerType), Literal.create(null, IntegerType)),
      null,
      row)

    // 2-arg substring from zero position
    checkEvaluation(
      Substring(s, Literal.create(0, IntegerType), Literal.create(Integer.MAX_VALUE, IntegerType)),
      "example",
      row)
    checkEvaluation(
      Substring(s, Literal.create(1, IntegerType), Literal.create(Integer.MAX_VALUE, IntegerType)),
      "example",
      row)

    // 2-arg substring from nonzero position
    checkEvaluation(
      Substring(s, Literal.create(2, IntegerType), Literal.create(Integer.MAX_VALUE, IntegerType)),
      "xample",
      row)

    // Substring with from negative position with negative length
    checkEvaluation(Substring(s, Literal.create(-1207959552, IntegerType),
      Literal.create(-1207959552, IntegerType)), "", row)

    val s_notNull = $"a".string.notNull.at(0)

    assert(Substring(s, Literal.create(0, IntegerType), Literal.create(2, IntegerType)).nullable)
    assert(
      Substring(s_notNull, Literal.create(0, IntegerType), Literal.create(2, IntegerType)).nullable
        === false)
    assert(Substring(s_notNull,
      Literal.create(null, IntegerType), Literal.create(2, IntegerType)).nullable)
    assert(Substring(s_notNull,
      Literal.create(0, IntegerType), Literal.create(null, IntegerType)).nullable)

    checkEvaluation(s.substr(0, 2), "ex", row)
    checkEvaluation(s.substr(0), "example", row)
    checkEvaluation(s.substring(0, 2), "ex", row)
    checkEvaluation(s.substring(0), "example", row)

    val bytes = Array[Byte](1, 2, 3, 4)
    checkEvaluation(Substring(bytes, 0, 2), Array[Byte](1, 2))
    checkEvaluation(Substring(bytes, 1, 2), Array[Byte](1, 2))
    checkEvaluation(Substring(bytes, 2, 2), Array[Byte](2, 3))
    checkEvaluation(Substring(bytes, 3, 2), Array[Byte](3, 4))
    checkEvaluation(Substring(bytes, 4, 2), Array[Byte](4))
    checkEvaluation(Substring(bytes, 8, 2), Array.empty[Byte])
    checkEvaluation(Substring(bytes, -1, 2), Array[Byte](4))
    checkEvaluation(Substring(bytes, -2, 2), Array[Byte](3, 4))
    checkEvaluation(Substring(bytes, -3, 2), Array[Byte](2, 3))
    checkEvaluation(Substring(bytes, -4, 2), Array[Byte](1, 2))
    checkEvaluation(Substring(bytes, -5, 2), Array[Byte](1))
    checkEvaluation(Substring(bytes, -8, 2), Array.empty[Byte])
  }

  test("string substring_index function") {
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(3)), "www.apache.org")
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(2)), "www.apache")
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(1)), "www")
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(0)), "")
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(-3)), "www.apache.org")
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(-2)), "apache.org")
    checkEvaluation(
      SubstringIndex(Literal("www.apache.org"), Literal("."), Literal(-1)), "org")
    checkEvaluation(
      SubstringIndex(Literal(""), Literal("."), Literal(-2)), "")
    checkEvaluation(
      SubstringIndex(Literal.create(null, StringType), Literal("."), Literal(-2)), null)
    checkEvaluation(SubstringIndex(
        Literal("www.apache.org"), Literal.create(null, StringType), Literal(-2)), null)
    // non ascii chars
    // scalastyle:off
    checkEvaluation(
      SubstringIndex(Literal("大千世界大千世界"), Literal( "千"), Literal(2)), "大千世界大")
    // scalastyle:on
    checkEvaluation(
      SubstringIndex(Literal("www||apache||org"), Literal( "||"), Literal(2)), "www||apache")
  }

  test("SPARK-40213: ascii for Latin-1 Supplement characters") {
    // scalastyle:off
    checkEvaluation(Ascii(Literal("¥")), 165, create_row("¥"))
    checkEvaluation(Ascii(Literal("®")), 174, create_row("®"))
    checkEvaluation(Ascii(Literal("©")), 169, create_row("©"))
    // scalastyle:on
    (128 until 256).foreach { c =>
      checkEvaluation(Ascii(Chr(Literal(c.toLong))), c, create_row(c.toLong))
    }
  }

  test("ascii for string") {
    val a = $"a".string.at(0)
    checkEvaluation(Ascii(Literal("efg")), 101, create_row("abdef"))
    checkEvaluation(Ascii(a), 97, create_row("abdef"))
    checkEvaluation(Ascii(a), 0, create_row(""))
    checkEvaluation(Ascii(a), null, create_row(null))
    checkEvaluation(Ascii(Literal.create(null, StringType)), null, create_row("abdef"))
  }

  test("string for ascii") {
    val a = $"a".long.at(0)
    checkEvaluation(Chr(Literal(48L)), "0", create_row("abdef"))
    checkEvaluation(Chr(a), "a", create_row(97L))
    checkEvaluation(Chr(a), "a", create_row(97L + 256L))
    checkEvaluation(Chr(a), "", create_row(-9L))
    checkEvaluation(Chr(a), Character.MIN_VALUE.toString, create_row(0L))
    checkEvaluation(Chr(a), Character.MIN_VALUE.toString, create_row(256L))
    checkEvaluation(Chr(a), null, create_row(null))
    checkEvaluation(Chr(a), 149.toChar.toString, create_row(149L))
    checkEvaluation(Chr(Literal.create(null, LongType)), null, create_row("abdef"))
  }

  test("base64/unbase64 for string") {
    val a = $"a".string.at(0)
    val b = $"b".binary.at(0)
    val bytes = Array[Byte](1, 2, 3, 4)

    checkEvaluation(Base64(Literal(bytes)), "AQIDBA==", create_row("abdef"))
    checkEvaluation(Base64(UnBase64(Literal("AQIDBA=="))), "AQIDBA==", create_row("abdef"))
    checkEvaluation(Base64(UnBase64(Literal(""))), "", create_row("abdef"))
    checkEvaluation(Base64(UnBase64(Literal.create(null, StringType))), null, create_row("abdef"))
    checkEvaluation(Base64(UnBase64(a)), "AQIDBA==", create_row("AQIDBA=="))

    checkEvaluation(Base64(b), "AQIDBA==", create_row(bytes))
    checkEvaluation(Base64(b), "", create_row(Array.empty[Byte]))
    checkEvaluation(Base64(b), null, create_row(null))
    checkEvaluation(Base64(Literal.create(null, BinaryType)), null, create_row("abdef"))

    checkEvaluation(UnBase64(a), null, create_row(null))
    checkEvaluation(UnBase64(Literal.create(null, StringType)), null, create_row("abdef"))
  }

  test("encode/decode for string") {
    val a = $"a".string.at(0)
    val b = $"b".binary.at(0)
    // scalastyle:off
    // non ascii characters are not allowed in the code, so we disable the scalastyle here.
    checkEvaluation(
      StringDecode(Encode(Literal("大千世界"), Literal("UTF-16LE")), Literal("UTF-16LE")), "大千世界")
    checkEvaluation(
      StringDecode(Encode(a, Literal("utf-8")), Literal("utf-8")), "大千世界", create_row("大千世界"))
    checkEvaluation(
      StringDecode(Encode(a, Literal("utf-8")), Literal("utf-8")), "", create_row(""))
    // scalastyle:on
    checkEvaluation(Encode(a, Literal("utf-8")), null, create_row(null))
    checkEvaluation(Encode(Literal.create(null, StringType), Literal("utf-8")), null)
    checkEvaluation(Encode(a, Literal.create(null, StringType)), null, create_row(""))

    checkEvaluation(StringDecode(b, Literal("utf-8")), null, create_row(null))
    checkEvaluation(StringDecode(Literal.create(null, BinaryType), Literal("utf-8")), null)
    checkEvaluation(StringDecode(b, Literal.create(null, StringType)), null, create_row(null))

    // Test escaping of charset
    GenerateUnsafeProjection.generate(Encode(a, Literal("\"quote")) :: Nil)
    GenerateUnsafeProjection.generate(StringDecode(b, Literal("\"quote")) :: Nil)
  }

  test("initcap unit test") {
    checkEvaluation(InitCap(Literal.create(null, StringType)), null)
    checkEvaluation(InitCap(Literal("a b")), "A B")
    checkEvaluation(InitCap(Literal(" a")), " A")
    checkEvaluation(InitCap(Literal("the test")), "The Test")
    checkEvaluation(InitCap(Literal("sParK")), "Spark")
    // scalastyle:off
    // non ascii characters are not allowed in the code, so we disable the scalastyle here.
    checkEvaluation(InitCap(Literal("世界")), "世界")
    // scalastyle:on
  }

  test("Levenshtein distance") {
    checkEvaluation(Levenshtein(Literal.create(null, StringType), Literal("")), null)
    checkEvaluation(Levenshtein(Literal(""), Literal.create(null, StringType)), null)
    checkEvaluation(Levenshtein(Literal(""), Literal("")), 0)
    checkEvaluation(Levenshtein(Literal("abc"), Literal("abc")), 0)
    checkEvaluation(Levenshtein(Literal("kitten"), Literal("sitting")), 3)
    checkEvaluation(Levenshtein(Literal("frog"), Literal("fog")), 1)
    // scalastyle:off
    // non ascii characters are not allowed in the code, so we disable the scalastyle here.
    checkEvaluation(Levenshtein(Literal("千世"), Literal("fog")), 3)
    checkEvaluation(Levenshtein(Literal("世界千世"), Literal("大a界b")), 4)
    // scalastyle:on

    // Test escaping of arguments:
    GenerateUnsafeProjection.generate(Levenshtein(Literal("\"quotea"), Literal("\"quoteb")) :: Nil)
  }

  test("soundex unit test") {
    checkEvaluation(SoundEx(Literal("ZIN")), "Z500")
    checkEvaluation(SoundEx(Literal("SU")), "S000")
    checkEvaluation(SoundEx(Literal("")), "")
    checkEvaluation(SoundEx(Literal.create(null, StringType)), null)

    // scalastyle:off
    // non ascii characters are not allowed in the code, so we disable the scalastyle here.
    checkEvaluation(SoundEx(Literal("测试")), "测试")
    checkEvaluation(SoundEx(Literal("Tschüss")), "T220")
    // scalastyle:on
    checkEvaluation(SoundEx(Literal("zZ")), "Z000", create_row("s8"))
    checkEvaluation(SoundEx(Literal("RAGSSEEESSSVEEWE")), "R221")
    checkEvaluation(SoundEx(Literal("Ashcraft")), "A261")
    checkEvaluation(SoundEx(Literal("Aswcraft")), "A261")
    checkEvaluation(SoundEx(Literal("Tymczak")), "T522")
    checkEvaluation(SoundEx(Literal("Pfister")), "P236")
    checkEvaluation(SoundEx(Literal("Miller")), "M460")
    checkEvaluation(SoundEx(Literal("Peterson")), "P362")
    checkEvaluation(SoundEx(Literal("Peters")), "P362")
    checkEvaluation(SoundEx(Literal("Auerbach")), "A612")
    checkEvaluation(SoundEx(Literal("Uhrbach")), "U612")
    checkEvaluation(SoundEx(Literal("Moskowitz")), "M232")
    checkEvaluation(SoundEx(Literal("Moskovitz")), "M213")
    checkEvaluation(SoundEx(Literal("relyheewsgeessg")), "R422")
    checkEvaluation(SoundEx(Literal("!!")), "!!")
  }

  test("replace") {
    checkEvaluation(
      StringReplace(Literal("replace"), Literal("pl"), Literal("123")), "re123ace")
    checkEvaluation(StringReplace(Literal("replace"), Literal("pl"), Literal("")), "reace")
    checkEvaluation(StringReplace(Literal("replace"), Literal(""), Literal("123")), "replace")
    checkEvaluation(StringReplace(Literal.create(null, StringType),
      Literal("pl"), Literal("123")), null)
    checkEvaluation(StringReplace(Literal("replace"),
      Literal.create(null, StringType), Literal("123")), null)
    checkEvaluation(StringReplace(Literal("replace"),
      Literal("pl"), Literal.create(null, StringType)), null)
    // test for multiple replace
    checkEvaluation(StringReplace(Literal("abcabc"), Literal("b"), Literal("12")), "a12ca12c")
    checkEvaluation(StringReplace(Literal("abcdabcd"), Literal("bc"), Literal("")), "adad")
    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(StringReplace(Literal("花花世界"), Literal("花世"), Literal("ab")), "花ab界")
    // scalastyle:on
  }

  test("overlay for string") {
    checkEvaluation(new Overlay(Literal("Spark SQL"), Literal("_"),
      Literal.create(6, IntegerType)), "Spark_SQL")
    checkEvaluation(new Overlay(Literal("Spark SQL"), Literal("CORE"),
      Literal.create(7, IntegerType)), "Spark CORE")
    checkEvaluation(Overlay(Literal("Spark SQL"), Literal("ANSI "),
      Literal.create(7, IntegerType), Literal.create(0, IntegerType)), "Spark ANSI SQL")
    checkEvaluation(Overlay(Literal("Spark SQL"), Literal("tructured"),
      Literal.create(2, IntegerType), Literal.create(4, IntegerType)), "Structured SQL")
    checkEvaluation(new Overlay(Literal.create(null, StringType), Literal("_"),
      Literal.create(6, IntegerType)), null)
    checkEvaluation(new Overlay(Literal.create(null, StringType), Literal("CORE"),
      Literal.create(7, IntegerType)), null)
    checkEvaluation(Overlay(Literal.create(null, StringType), Literal("ANSI "),
      Literal.create(7, IntegerType), Literal.create(0, IntegerType)), null)
    checkEvaluation(Overlay(Literal.create(null, StringType), Literal("tructured"),
      Literal.create(2, IntegerType), Literal.create(4, IntegerType)), null)
    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(new Overlay(Literal("Spark的SQL"), Literal("_"),
      Literal.create(6, IntegerType)), "Spark_SQL")
    // scalastyle:on
    // position greater than the length of input string
    checkEvaluation(new Overlay(Literal("Spark SQL"), Literal("_"),
      Literal.create(10, IntegerType)), "Spark SQL_")
    checkEvaluation(Overlay(Literal("Spark SQL"), Literal("_"),
      Literal.create(10, IntegerType), Literal.create(4, IntegerType)), "Spark SQL_")
    // position is zero
    checkEvaluation(new Overlay(Literal("Spark SQL"), Literal("__"),
      Literal.create(0, IntegerType)), "__park SQL")
    checkEvaluation(Overlay(Literal("Spark SQL"), Literal("__"),
      Literal.create(0, IntegerType), Literal.create(4, IntegerType)), "__rk SQL")
    // position is negative
    checkEvaluation(new Overlay(Literal("Spark SQL"), Literal("__"),
      Literal.create(-10, IntegerType)), "__park SQL")
    checkEvaluation(Overlay(Literal("Spark SQL"), Literal("__"),
      Literal.create(-10, IntegerType), Literal.create(4, IntegerType)), "__rk SQL")
  }

  test("overlay for byte array") {
    val input = Literal(Array[Byte](1, 2, 3, 4, 5, 6, 7, 8, 9))
    checkEvaluation(new Overlay(input, Literal(Array[Byte](-1)),
      Literal.create(6, IntegerType)), Array[Byte](1, 2, 3, 4, 5, -1, 7, 8, 9))
    checkEvaluation(new Overlay(input, Literal(Array[Byte](-1, -1, -1, -1)),
      Literal.create(7, IntegerType)), Array[Byte](1, 2, 3, 4, 5, 6, -1, -1, -1, -1))
    checkEvaluation(Overlay(input, Literal(Array[Byte](-1, -1)), Literal.create(7, IntegerType),
      Literal.create(0, IntegerType)), Array[Byte](1, 2, 3, 4, 5, 6, -1, -1, 7, 8, 9))
    checkEvaluation(Overlay(input, Literal(Array[Byte](-1, -1, -1, -1, -1)),
      Literal.create(2, IntegerType), Literal.create(4, IntegerType)),
      Array[Byte](1, -1, -1, -1, -1, -1, 6, 7, 8, 9))

    val nullInput = Literal.create(null, BinaryType)
    checkEvaluation(new Overlay(nullInput, Literal(Array[Byte](-1)),
      Literal.create(6, IntegerType)), null)
    checkEvaluation(new Overlay(nullInput, Literal(Array[Byte](-1, -1, -1, -1)),
      Literal.create(7, IntegerType)), null)
    checkEvaluation(Overlay(nullInput, Literal(Array[Byte](-1, -1)),
      Literal.create(7, IntegerType), Literal.create(0, IntegerType)), null)
    checkEvaluation(Overlay(nullInput, Literal(Array[Byte](-1, -1, -1, -1, -1)),
      Literal.create(2, IntegerType), Literal.create(4, IntegerType)), null)
    // position greater than the length of input byte array
    checkEvaluation(new Overlay(input, Literal(Array[Byte](-1)),
      Literal.create(10, IntegerType)), Array[Byte](1, 2, 3, 4, 5, 6, 7, 8, 9, -1))
    checkEvaluation(Overlay(input, Literal(Array[Byte](-1)), Literal.create(10, IntegerType),
      Literal.create(4, IntegerType)), Array[Byte](1, 2, 3, 4, 5, 6, 7, 8, 9, -1))
    // position is zero
    checkEvaluation(new Overlay(input, Literal(Array[Byte](-1, -1)),
      Literal.create(0, IntegerType)), Array[Byte](-1, -1, 2, 3, 4, 5, 6, 7, 8, 9))
    checkEvaluation(Overlay(input, Literal(Array[Byte](-1, -1)), Literal.create(0, IntegerType),
      Literal.create(4, IntegerType)), Array[Byte](-1, -1, 4, 5, 6, 7, 8, 9))
    // position is negative
    checkEvaluation(new Overlay(input, Literal(Array[Byte](-1, -1)),
      Literal.create(-10, IntegerType)), Array[Byte](-1, -1, 2, 3, 4, 5, 6, 7, 8, 9))
    checkEvaluation(Overlay(input, Literal(Array[Byte](-1, -1)), Literal.create(-10, IntegerType),
      Literal.create(4, IntegerType)), Array[Byte](-1, -1, 4, 5, 6, 7, 8, 9))
  }

  test("Check Overlay.checkInputDataTypes results") {
    assert(new Overlay(Literal("Spark SQL"), Literal("_"),
      Literal.create(6, IntegerType)).checkInputDataTypes().isSuccess)
    assert(Overlay(Literal("Spark SQL"), Literal("ANSI "), Literal.create(7, IntegerType),
      Literal.create(0, IntegerType)).checkInputDataTypes().isSuccess)
    assert(new Overlay(Literal.create("Spark SQL".getBytes), Literal.create("_".getBytes),
      Literal.create(6, IntegerType)).checkInputDataTypes().isSuccess)
    assert(Overlay(Literal.create("Spark SQL".getBytes), Literal.create("ANSI ".getBytes),
      Literal.create(7, IntegerType), Literal.create(0, IntegerType))
      .checkInputDataTypes().isSuccess)
    assert(new Overlay(Literal.create(1), Literal.create(2), Literal.create(0, IntegerType))
      .checkInputDataTypes().isFailure)
    assert(Overlay(Literal("Spark SQL"), Literal.create(2), Literal.create(7, IntegerType),
      Literal.create(0, IntegerType)).checkInputDataTypes().isFailure)
  }

  test("translate") {
    checkEvaluation(
      StringTranslate(Literal("translate"), Literal("rnlt"), Literal("123")), "1a2s3ae")
    checkEvaluation(StringTranslate(Literal("translate"), Literal(""), Literal("123")), "translate")
    checkEvaluation(StringTranslate(Literal("translate"), Literal("rnlt"), Literal("")), "asae")
    // test for multiple mapping
    checkEvaluation(StringTranslate(Literal("abcd"), Literal("aba"), Literal("123")), "12cd")
    checkEvaluation(StringTranslate(Literal("abcd"), Literal("aba"), Literal("12")), "12cd")
    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(StringTranslate(Literal("花花世界"), Literal("花界"), Literal("ab")), "aa世b")
    // test for unicode characters whose code point >= 0x10000
    checkEvaluation(
      StringTranslate(
        Literal("\uD840\uDC0Bxyza\uD867\uDE49c123b\uD842\uDFB7\uD867\uDE3D"),
        Literal("\uD867\uDE3Da\uD842\uDFB7b\uD840\uDC0Bc\uD867\uDE49c"),
        Literal("1\uD83C\uDF3B2\uD83C\uDF37\uD83D\uDC15\uD83D\uDC08\uD83C\uDF38")),
      "\uD83D\uDC15xyz\uD83C\uDF3B\uD83C\uDF38\uD83D\uDC08123\uD83C\uDF3721")
    // scalastyle:on
  }

  test("TRIM") {
    val s = $"a".string.at(0)
    checkEvaluation(StringTrim(Literal(" aa  ")), "aa", create_row(" abdef "))
    checkEvaluation(StringTrim("aa", "a"), "", create_row(" abdef "))
    checkEvaluation(StringTrim(Literal(" aabbtrimccc"), "ab cd"), "trim", create_row("bdef"))
    checkEvaluation(StringTrim(Literal("a<a >@>.,>"), "a.,@<>"), " ", create_row(" abdef "))
    checkEvaluation(StringTrim(s), "abdef", create_row(" abdef "))
    checkEvaluation(StringTrim(s, "abd"), "ef", create_row("abdefa"))
    checkEvaluation(StringTrim(s, "a"), "bdef", create_row("aaabdefaaaa"))
    checkEvaluation(StringTrim(s, "SLSQ"), "park", create_row("SSparkSQLS"))

    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(StringTrim(s), "花花世界", create_row("  花花世界 "))
    checkEvaluation(StringTrim(s, "花世界"), "", create_row("花花世界花花"))
    checkEvaluation(StringTrim(s, "花 "), "世界", create_row(" 花花世界花花"))
    checkEvaluation(StringTrim(s, "花 "), "世界", create_row(" 花 花 世界 花 花 "))
    checkEvaluation(StringTrim(s, "a花世"), "界", create_row("aa花花世界花花aa"))
    checkEvaluation(StringTrim(s, "a@#( )"), "花花世界花花", create_row("aa()花花世界花花@ #"))
    checkEvaluation(StringTrim(Literal("花trim"), "花 "), "trim", create_row(" abdef "))
    // scalastyle:on
    checkEvaluation(StringTrim(Literal("a"), Literal.create(null, StringType)), null)
    checkEvaluation(StringTrim(Literal.create(null, StringType), Literal("a")), null)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(StringTrim(Literal("\"quote"), Literal("\"quote")) :: Nil)

    checkEvaluation(StringTrim(Literal("yxTomxx"), Literal("xyz")), "Tom")
    checkEvaluation(StringTrim(Literal("xxxbarxxx"), Literal("x")), "bar")
  }

  test("LTRIM") {
    val s = $"a".string.at(0)
    checkEvaluation(StringTrimLeft(Literal(" aa  ")), "aa  ", create_row(" abdef "))
    checkEvaluation(StringTrimLeft(Literal("aa"), "a"), "", create_row(" abdef "))
    checkEvaluation(StringTrimLeft(Literal("aa "), "a "), "", create_row(" abdef "))
    checkEvaluation(StringTrimLeft(Literal("aabbcaaaa"), "ab"), "caaaa", create_row(" abdef "))
    checkEvaluation(StringTrimLeft(s), "abdef ", create_row(" abdef "))
    checkEvaluation(StringTrimLeft(s, "a"), "bdefa", create_row("abdefa"))
    checkEvaluation(StringTrimLeft(s, "a "), "bdefaaaa", create_row(" aaabdefaaaa"))
    checkEvaluation(StringTrimLeft(s, "Spk"), "arkSQLS", create_row("SSparkSQLS"))

    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(StringTrimLeft(s), "花花世界 ", create_row("  花花世界 "))
    checkEvaluation(StringTrimLeft(s, "花"), "世界花花", create_row("花花世界花花"))
    checkEvaluation(StringTrimLeft(s, "花 世"), "界花花", create_row(" 花花世界花花"))
    checkEvaluation(StringTrimLeft(s, "花"), "a花花世界花花 ", create_row("a花花世界花花 "))
    checkEvaluation(StringTrimLeft(s, "a花界"), "世界花花aa", create_row("aa花花世界花花aa"))
    checkEvaluation(StringTrimLeft(s, "a世界"), "花花世界花花", create_row("花花世界花花"))
    // scalastyle:on
    checkEvaluation(StringTrimLeft(Literal.create(null, StringType), Literal("a")), null)
    checkEvaluation(StringTrimLeft(Literal("a"), Literal.create(null, StringType)), null)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(
      StringTrimLeft(Literal("\"quote"), Literal("\"quote")) :: Nil)

    checkEvaluation(StringTrimLeft(Literal("zzzytest"), Literal("xyz")), "test")
    checkEvaluation(StringTrimLeft(Literal("zzzytestxyz"), Literal("xyz")), "testxyz")
    checkEvaluation(StringTrimLeft(Literal("xyxXxyLAST WORD"), Literal("xy")), "XxyLAST WORD")
  }

  test("RTRIM") {
    val s = $"a".string.at(0)
    checkEvaluation(StringTrimRight(Literal(" aa  ")), " aa", create_row(" abdef "))
    checkEvaluation(StringTrimRight(Literal("a"), "a"), "", create_row(" abdef "))
    checkEvaluation(StringTrimRight(Literal("ab"), "ab"), "", create_row(" abdef "))
    checkEvaluation(StringTrimRight(Literal("aabbaaaa %"), "a %"), "aabb", create_row("def"))
    checkEvaluation(StringTrimRight(s), " abdef", create_row(" abdef "))
    checkEvaluation(StringTrimRight(s, "a"), "abdef", create_row("abdefa"))
    checkEvaluation(StringTrimRight(s, "abf de"), "", create_row(" aaabdefaaaa"))
    checkEvaluation(StringTrimRight(s, "S*&"), "SSparkSQL", create_row("SSparkSQLS*"))

    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(StringTrimRight(Literal("a"), "花"), "a", create_row(" abdef "))
    checkEvaluation(StringTrimRight(Literal("花"), "a"), "花", create_row(" abdef "))
    checkEvaluation(StringTrimRight(Literal("花花世界"), "界花世"), "", create_row(" abdef "))
    checkEvaluation(StringTrimRight(s), "  花花世界", create_row("  花花世界 "))
    checkEvaluation(StringTrimRight(s, "花a#"), "花花世界", create_row("花花世界花花###aa花"))
    checkEvaluation(StringTrimRight(s, "花"), "", create_row("花花花花"))
    checkEvaluation(StringTrimRight(s, "花 界b@"), " 花花世", create_row(" 花花世 b界@花花 "))
    // scalastyle:on
    checkEvaluation(StringTrimRight(Literal("a"), Literal.create(null, StringType)), null)
    checkEvaluation(StringTrimRight(Literal.create(null, StringType), Literal("a")), null)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(
      StringTrimRight(Literal("\"quote"), Literal("\"quote")) :: Nil)

    checkEvaluation(StringTrimRight(Literal("testxxzx"), Literal("xyz")), "test")
    checkEvaluation(StringTrimRight(Literal("xyztestxxzx"), Literal("xyz")), "xyztest")
    checkEvaluation(StringTrimRight(Literal("TURNERyxXxy"), Literal("xy")), "TURNERyxX")
  }

  test("FORMAT") {
    checkEvaluation(FormatString(Literal("aa%d%s"), Literal(123), Literal("a")), "aa123a")
    checkEvaluation(FormatString(Literal("aa")), "aa", create_row(null))
    checkEvaluation(FormatString(Literal("aa%d%s"), Literal(123), Literal("a")), "aa123a")
    checkEvaluation(FormatString(Literal("aa%d%s"), 12, "cc"), "aa12cc")

    checkEvaluation(FormatString(Literal.create(null, StringType), 12, "cc"), null)
    checkEvaluation(
      FormatString(Literal("aa%d%s"), Literal.create(null, IntegerType), "cc"), "aanullcc")
    checkEvaluation(
      FormatString(Literal("aa%d%s"), 12, Literal.create(null, StringType)), "aa12null")

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(FormatString(Literal("\"quote"), Literal("\"quote")) :: Nil)
  }

  test("SPARK-22603: FormatString should not generate codes beyond 64KB") {
    val N = 4500
    val args = (1 to N).map(i => Literal.create(i.toString, StringType))
    val format = "%s" * N
    val expected = (1 to N).map(i => i.toString).mkString
    checkEvaluation(FormatString(Literal(format) +: args: _*), expected)
  }

  test("INSTR") {
    val s1 = $"a".string.at(0)
    val s2 = $"b".string.at(1)
    val s3 = $"c".string.at(2)
    val row1 = create_row("aaads", "aa", "zz")

    checkEvaluation(StringInstr(Literal("aaads"), Literal("aa")), 1, row1)
    checkEvaluation(StringInstr(Literal("aaads"), Literal("de")), 0, row1)
    checkEvaluation(StringInstr(Literal.create(null, StringType), Literal("de")), null, row1)
    checkEvaluation(StringInstr(Literal("aaads"), Literal.create(null, StringType)), null, row1)

    checkEvaluation(StringInstr(s1, s2), 1, row1)
    checkEvaluation(StringInstr(s1, s3), 0, row1)

    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(StringInstr(s1, s2), 3, create_row("花花世界", "世界"))
    checkEvaluation(StringInstr(s1, s2), 1, create_row("花花世界", "花"))
    checkEvaluation(StringInstr(s1, s2), 0, create_row("花花世界", "小"))
    // scalastyle:on

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(StringInstr(Literal("\"quote"), Literal("\"quote")) :: Nil)
  }

  test("LOCATE") {
    val s1 = $"a".string.at(0)
    val s2 = $"b".string.at(1)
    val s3 = $"c".string.at(2)
    val s4 = $"d".int.at(3)
    val row1 = create_row("aaads", "aa", "zz", 2)
    val row2 = create_row(null, "aa", "zz", 1)
    val row3 = create_row("aaads", null, "zz", 1)
    val row4 = create_row(null, null, null, 1)

    checkEvaluation(new StringLocate(Literal("aa"), Literal("aaads")), 1, row1)
    checkEvaluation(StringLocate(Literal("aa"), Literal("aaads"), Literal(0)), 0, row1)
    checkEvaluation(StringLocate(Literal("aa"), Literal("aaads"), Literal(1)), 1, row1)
    checkEvaluation(StringLocate(Literal("aa"), Literal("aaads"), Literal(2)), 2, row1)
    checkEvaluation(StringLocate(Literal("aa"), Literal("aaads"), Literal(3)), 0, row1)
    checkEvaluation(new StringLocate(Literal("de"), Literal("aaads")), 0, row1)
    checkEvaluation(StringLocate(Literal("de"), Literal("aaads"), 2), 0, row1)

    checkEvaluation(new StringLocate(s2, s1), 1, row1)
    checkEvaluation(StringLocate(s2, s1, s4), 2, row1)
    checkEvaluation(new StringLocate(s3, s1), 0, row1)
    checkEvaluation(StringLocate(s3, s1, Literal.create(null, IntegerType)), 0, row1)
    checkEvaluation(new StringLocate(s2, s1), null, row2)
    checkEvaluation(new StringLocate(s2, s1), null, row3)
    checkEvaluation(new StringLocate(s2, s1, Literal.create(null, IntegerType)), 0, row4)
  }

  test("LPAD/RPAD") {
    val s1 = $"a".string.at(0)
    val s2 = $"b".int.at(1)
    val s3 = $"c".string.at(2)
    val row1 = create_row("hi", 5, "??")
    val row2 = create_row("hi", 1, "?")
    val row3 = create_row(null, 1, "?")
    val row4 = create_row("hi", null, "?")
    val row5 = create_row("hi", 1, null)

    checkEvaluation(StringLPad(Literal("hi"), Literal(5), Literal("??")), "???hi", row1)
    checkEvaluation(StringLPad(Literal("hi"), Literal(1), Literal("??")), "h", row1)
    checkEvaluation(StringLPad(s1, s2, s3), "???hi", row1)
    checkEvaluation(StringLPad(s1, s2, s3), "h", row2)
    checkEvaluation(StringLPad(s1, s2, s3), null, row3)
    checkEvaluation(StringLPad(s1, s2, s3), null, row4)
    checkEvaluation(StringLPad(s1, s2, s3), null, row5)
    checkEvaluation(StringLPad(Literal("hi"), Literal(5), Literal(" ")), "   hi")
    checkEvaluation(StringLPad(Literal("hi"), Literal(1), Literal(" ")), "h")

    checkEvaluation(StringRPad(Literal("hi"), Literal(5), Literal("??")), "hi???", row1)
    checkEvaluation(StringRPad(Literal("hi"), Literal(1), Literal("??")), "h", row1)
    checkEvaluation(StringRPad(s1, s2, s3), "hi???", row1)
    checkEvaluation(StringRPad(s1, s2, s3), "h", row2)
    checkEvaluation(StringRPad(s1, s2, s3), null, row3)
    checkEvaluation(StringRPad(s1, s2, s3), null, row4)
    checkEvaluation(StringRPad(s1, s2, s3), null, row5)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(StringLPad(Literal("\"quote"), s2, Literal("\"quote")) :: Nil)
    GenerateUnsafeProjection.generate(StringRPad(Literal("\"quote"), s2, Literal("\"quote")) :: Nil)
    checkEvaluation(StringRPad(Literal("hi"), Literal(5)), "hi   ")
    checkEvaluation(StringRPad(Literal("hi"), Literal(1)), "h")
  }

  test("PadExpressionBuilderBase") {
    // test if the correct lpad/rpad expression is created given different parameter types
    Seq(true, false).foreach { confVal =>
      SQLConf.get.setConf(SQLConf.LEGACY_LPAD_RPAD_BINARY_TYPE_AS_STRING, confVal)

      val lpadExp1 = LPadExpressionBuilder.build("lpad", Seq(Literal("hi"), Literal(5)))
      val lpadExp2 = LPadExpressionBuilder.build("lpad", Seq(Literal(Array[Byte]()), Literal(5)))
      val lpadExp3 = LPadExpressionBuilder.build("lpad",
        Seq(Literal("hi"), Literal(5), Literal("somepadding")))
      val lpadExp4 = LPadExpressionBuilder.build("lpad",
        Seq(Literal(Array[Byte](1, 2)), Literal(5), Literal("somepadding")))
      val lpadExp5 = LPadExpressionBuilder.build("lpad",
        Seq(Literal(Array[Byte](1, 2)), Literal(5), Literal(Array[Byte](1))))

      val rpadExp1 = RPadExpressionBuilder.build("rpad", Seq(Literal("hi"), Literal(5)))
      val rpadExp2 = RPadExpressionBuilder.build("rpad", Seq(Literal(Array[Byte]()), Literal(5)))
      val rpadExp3 = RPadExpressionBuilder.build("rpad",
        Seq(Literal("hi"), Literal(5), Literal("somepadding")))
      val rpadExp4 = RPadExpressionBuilder.build("rpad",
        Seq(Literal(Array[Byte](1, 2)), Literal(5), Literal("somepadding")))
      val rpadExp5 = RPadExpressionBuilder.build("rpad",
        Seq(Literal(Array[Byte](1, 2)), Literal(5), Literal(Array[Byte](1))))

      assert(lpadExp1 == StringLPad(Literal("hi"), Literal(5), Literal(" ")))
      assert(lpadExp3 == StringLPad(Literal("hi"), Literal(5), Literal("somepadding")))
      assert(lpadExp4 == StringLPad(Literal(Array[Byte](1, 2)), Literal(5), Literal("somepadding")))

      assert(rpadExp1 == StringRPad(Literal("hi"), Literal(5), Literal(" ")))
      assert(rpadExp3 == StringRPad(Literal("hi"), Literal(5), Literal("somepadding")))
      assert(rpadExp4 == StringRPad(Literal(Array[Byte](1, 2)), Literal(5), Literal("somepadding")))

      if (!SQLConf.get.getConf(SQLConf.LEGACY_LPAD_RPAD_BINARY_TYPE_AS_STRING)) {
        assert(lpadExp2 ==
          BinaryPad("lpad", Literal(Array[Byte]()), Literal(5), Literal(Array[Byte](0))))
        assert(lpadExp5 ==
          BinaryPad("lpad", Literal(Array[Byte](1, 2)), Literal(5), Literal(Array[Byte](1))))

        assert(rpadExp2 ==
          BinaryPad("rpad", Literal(Array[Byte]()), Literal(5), Literal(Array[Byte](0))))
        assert(rpadExp5 ==
          BinaryPad("rpad", Literal(Array[Byte](1, 2)), Literal(5), Literal(Array[Byte](1))))
      } else {
        assert(lpadExp2 ==
          StringLPad(Literal(Array[Byte]()), Literal(5), Literal(" ")))
        assert(lpadExp5 ==
          StringLPad(Literal(Array[Byte](1, 2)), Literal(5), Literal(Array[Byte](1))))

        assert(rpadExp2 ==
          StringRPad(Literal(Array[Byte]()), Literal(5), Literal(" ")))
        assert(rpadExp5 ==
          StringRPad(Literal(Array[Byte](1, 2)), Literal(5), Literal(Array[Byte](1))))
      }
    }
  }

  test("REPEAT") {
    val s1 = $"a".string.at(0)
    val s2 = $"b".int.at(1)
    val row1 = create_row("hi", 2)
    val row2 = create_row(null, 1)

    checkEvaluation(StringRepeat(Literal("hi"), Literal(2)), "hihi", row1)
    checkEvaluation(StringRepeat(Literal("hi"), Literal(-1)), "", row1)
    checkEvaluation(StringRepeat(s1, s2), "hihi", row1)
    checkEvaluation(StringRepeat(s1, s2), null, row2)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(StringRepeat(Literal("\"quote"), Literal(2)) :: Nil)
  }

  test("REVERSE") {
    val s = $"a".string.at(0)
    val row1 = create_row("abccc")
    checkEvaluation(Reverse(Literal("abccc")), "cccba", row1)
    checkEvaluation(Reverse(s), "cccba", row1)
    checkEvaluation(Reverse(Literal.create(null, StringType)), null, row1)
  }

  test("SPACE") {
    val s1 = $"b".int.at(0)
    val row1 = create_row(2)
    val row2 = create_row(null)

    checkEvaluation(StringSpace(Literal(2)), "  ", row1)
    checkEvaluation(StringSpace(Literal(-1)), "", row1)
    checkEvaluation(StringSpace(Literal(0)), "", row1)
    checkEvaluation(StringSpace(s1), "  ", row1)
    checkEvaluation(StringSpace(s1), null, row2)
  }

  test("length for string / binary") {
    val a = $"a".string.at(0)
    val b = $"b".binary.at(0)
    val bytes = Array[Byte](1, 2, 3, 1, 2)
    val string = "abdef"

    // scalastyle:off
    // non ascii characters are not allowed in the source code, so we disable the scalastyle.
    checkEvaluation(Length(Literal("a花花c")), 4, create_row(string))
    checkEvaluation(OctetLength(Literal("a花花c")), 8, create_row(string))
    checkEvaluation(BitLength(Literal("a花花c")), 8 * 8, create_row(string))
    // scalastyle:on
    checkEvaluation(Length(Literal(bytes)), 5, create_row(Array.empty[Byte]))
    checkEvaluation(OctetLength(Literal(bytes)), 5, create_row(Array.empty[Byte]))
    checkEvaluation(BitLength(Literal(bytes)), 5 * 8, create_row(Array.empty[Byte]))

    checkEvaluation(Length(a), 5, create_row(string))
    checkEvaluation(OctetLength(a), 5, create_row(string))
    checkEvaluation(BitLength(a), 5 * 8, create_row(string))
    checkEvaluation(Length(b), 5, create_row(bytes))
    checkEvaluation(OctetLength(b), 5, create_row(bytes))
    checkEvaluation(BitLength(b), 5 * 8, create_row(bytes))

    checkEvaluation(Length(a), 0, create_row(""))
    checkEvaluation(OctetLength(a), 0, create_row(""))
    checkEvaluation(BitLength(a), 0, create_row(""))
    checkEvaluation(Length(b), 0, create_row(Array.empty[Byte]))
    checkEvaluation(OctetLength(b), 0, create_row(Array.empty[Byte]))
    checkEvaluation(BitLength(b), 0, create_row(Array.empty[Byte]))

    checkEvaluation(Length(a), null, create_row(null))
    checkEvaluation(OctetLength(a), null, create_row(null))
    checkEvaluation(BitLength(a), null, create_row(null))
    checkEvaluation(Length(b), null, create_row(null))
    checkEvaluation(OctetLength(b), null, create_row(null))
    checkEvaluation(BitLength(b), null, create_row(null))

    checkEvaluation(Length(Literal.create(null, StringType)), null, create_row(string))
    checkEvaluation(OctetLength(Literal.create(null, StringType)), null, create_row(string))
    checkEvaluation(BitLength(Literal.create(null, StringType)), null, create_row(string))
    checkEvaluation(Length(Literal.create(null, BinaryType)), null, create_row(bytes))
    checkEvaluation(OctetLength(Literal.create(null, BinaryType)), null, create_row(bytes))
    checkEvaluation(BitLength(Literal.create(null, BinaryType)), null, create_row(bytes))
  }

  test("format_number / FormatNumber") {
    checkEvaluation(FormatNumber(Literal(4.asInstanceOf[Byte]), Literal(3)), "4.000")
    checkEvaluation(FormatNumber(Literal(4.asInstanceOf[Short]), Literal(3)), "4.000")
    checkEvaluation(FormatNumber(Literal(4.0f), Literal(3)), "4.000")
    checkEvaluation(FormatNumber(Literal(4), Literal(3)), "4.000")
    checkEvaluation(FormatNumber(Literal(12831273.23481d), Literal(3)), "12,831,273.235")
    checkEvaluation(FormatNumber(Literal(12831273.83421d), Literal(0)), "12,831,274")
    checkEvaluation(FormatNumber(Literal(123123324123L), Literal(3)), "123,123,324,123.000")
    checkEvaluation(FormatNumber(Literal(123123324123L), Literal(-1)), null)
    checkEvaluation(
      FormatNumber(
        Literal(Decimal(123123324123L) * Decimal(123123.21234d)), Literal(4)),
      "15,159,339,180,002,773.2778")
    checkEvaluation(FormatNumber(Literal.create(null, IntegerType), Literal(3)), null)
    assert(FormatNumber(Literal.create(null, NullType), Literal(3)).resolved === false)

    checkEvaluation(FormatNumber(Literal(12332.123456), Literal("##############.###")), "12332.123")
    checkEvaluation(FormatNumber(Literal(12332.123456), Literal("##.###")), "12332.123")
    checkEvaluation(FormatNumber(Literal(4.asInstanceOf[Byte]), Literal("##.####")), "4")
    checkEvaluation(FormatNumber(Literal(4.asInstanceOf[Short]), Literal("##.####")), "4")
    checkEvaluation(FormatNumber(Literal(4.0f), Literal("##.###")), "4")
    checkEvaluation(FormatNumber(Literal(4), Literal("##.###")), "4")
    checkEvaluation(FormatNumber(Literal(12831273.23481d),
      Literal("###,###,###,###,###.###")), "12,831,273.235")
    checkEvaluation(FormatNumber(Literal(12831273.83421d), Literal("")), "12,831,274")
    checkEvaluation(FormatNumber(Literal(123123324123L), Literal("###,###,###,###,###.###")),
      "123,123,324,123")
    checkEvaluation(
      FormatNumber(Literal(Decimal(123123324123L) * Decimal(123123.21234d)),
        Literal("###,###,###,###,###.####")), "15,159,339,180,002,773.2778")
    checkEvaluation(FormatNumber(Literal.create(null, IntegerType), Literal("##.###")), null)
    assert(FormatNumber(Literal.create(null, NullType), Literal("##.###")).resolved === false)

    checkEvaluation(FormatNumber(Literal(12332.123456), Literal("#,###,###,###,###,###,##0")),
      "12,332")
    checkEvaluation(FormatNumber(
      Literal.create(null, IntegerType), Literal.create(null, StringType)), null)
    checkEvaluation(FormatNumber(
      Literal.create(null, IntegerType), Literal.create(null, IntegerType)), null)
  }

  test("ToNumber: positive tests") {
    Seq(
      ("$345", "S$999,099.99") -> Decimal(345),
      ("-$12,345.67", "S$999,099.99") -> Decimal(-12345.67),
      ("454,123", "999,099") -> Decimal(454123),
      ("$045", "S$999,099.99") -> Decimal(45),
      ("454", "099") -> Decimal(454),
      ("454.", "099.99") -> Decimal(454.0),
      ("454.6", "099D99") -> Decimal(454.6),
      ("454.67", "099.00") -> Decimal(454.67),
      ("454", "000") -> Decimal(454),
      ("  454 ", "9099") -> Decimal(454),
      ("454", "099") -> Decimal(454),
      ("454.67", "099.99") -> Decimal(454.67),
      ("$454", "$999") -> Decimal(454),
      ("  454,123 ", "999G099") -> Decimal(454123),
      ("$454,123", "$999G099") -> Decimal(454123),
      ("+$89,1,2,3,45.123", "S$999,0,0,0,999.00000") -> Decimal(8912345.123),
      ("-454", "S999") -> Decimal(-454),
      ("+454", "S999") -> Decimal(454),
      ("454", "999PR") -> Decimal(454),
      (" 454 ", "999PR") -> Decimal(454),
      ("454-", "999MI") -> Decimal(-454),
      ("-$54", "MI$99") -> Decimal(-54),
      // The input string contains more digits than fit in a long integer.
      ("123,456,789,123,456,789,123", "999,999,999,999,999,999,999") ->
        Decimal(new JavaBigDecimal("123456789123456789123"))
    ).foreach { case ((str: String, format: String), expected: Decimal) =>
      val toNumberExpr = ToNumber(Literal(str), Literal(format))
      assert(toNumberExpr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(toNumberExpr, expected)

      val tryToNumberExpr = TryToNumber(Literal(str), Literal(format))
      assert(tryToNumberExpr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(tryToNumberExpr, expected)
    }

    for (i <- 0 to 2) {
      for (j <- 3 to 5) {
        for (k <- 6 to 9) {
          Seq(
            (s"$i$j$k", "999") -> Decimal(s"$i$j$k".toInt),
            (s"$i$j$k", "S099.") -> Decimal(s"$i$j$k".toInt),
            (s"$i$j.$k", "99.9") -> Decimal(s"$i$j.$k".toDouble),
            (s"$i,$j,$k", "999,999,0") -> Decimal(s"$i$j$k".toInt)
          ).foreach { case ((str: String, format: String), expected: Decimal) =>
            val toNumberExpr = ToNumber(Literal(str), Literal(format))
            assert(toNumberExpr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
            checkEvaluation(toNumberExpr, expected)

            val tryToNumberExpr = TryToNumber(Literal(str), Literal(format))
            assert(tryToNumberExpr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
            checkEvaluation(tryToNumberExpr, expected)
          }
        }
      }
    }
  }

  test("ToNumber and ToCharacter: negative tests (the format string is invalid)") {
    val unexpectedCharacter = "the structure of the format string must match: " +
      "[MI|S] [$] [0|9|G|,]* [.|D] [0|9]* [$] [PR|MI|S]"
    val thousandsSeparatorDigitsBetween =
      "Thousands separators (, or G) must have digits in between them"
    val mustBeAtEnd = "must be at the end of the number format"
    val atMostOne = "At most one"
    Seq(
      // The format string must not be empty.
      ("454", "") -> "The format string cannot be empty",
      // Make sure the format string does not contain any unrecognized characters.
      ("454", "999@") -> unexpectedCharacter,
      ("454", "999M") -> unexpectedCharacter,
      ("454", "999P") -> unexpectedCharacter,
      // Make sure the format string contains at least one digit.
      ("454", "$") -> "The format string requires at least one number digit",
      // Make sure the format string contains at most one decimal point.
      ("454", "99.99.99") -> atMostOne,
      // Make sure the format string contains at most one dollar sign.
      ("454", "$$99") -> atMostOne,
      // Make sure the format string contains at most one minus sign at the beginning or end.
      ("$4-4", "$9MI9") -> unexpectedCharacter,
      ("--4", "SMI9") -> unexpectedCharacter,
      ("--$54", "SS$99") -> atMostOne,
      ("-$54", "MI$99MI") -> atMostOne,
      ("$4-4", "$9MI9MI") -> atMostOne,
      // Make sure the format string contains at most one closing angle bracket at the end.
      ("<$45>", "PR$99") -> unexpectedCharacter,
      ("$4<4>", "$9PR9") -> unexpectedCharacter,
      ("<<454>>", "999PRPR") -> atMostOne,
      // Make sure that any dollar sign in the format string occurs before any digits.
      ("4$54", "9$99") -> "Currency characters must appear before digits",
      // Make sure that any dollar sign in the format string occurs before any decimal point.
      (".$99", ".$99") -> "Currency characters must appear before any decimal point",
      // Thousands separators must have digits in between them.
      (",123", ",099") -> thousandsSeparatorDigitsBetween,
      (",123,456", ",999,099") -> thousandsSeparatorDigitsBetween,
      (",,345", "9,,09.99") -> thousandsSeparatorDigitsBetween,
      (",,345", "9,99,.99") -> thousandsSeparatorDigitsBetween,
      (",,345", "9,99,") -> thousandsSeparatorDigitsBetween,
      (",,345", ",,999,099.99") -> thousandsSeparatorDigitsBetween,
      // Thousands separators must not appear after the decimal point.
      ("123.45,6", "099.99,9") ->
        "Thousands separators (, or G) may not appear after the decimal point"
    ).foreach { case ((str: String, format: String), expectedErrMsg: String) =>
      val toNumberResult = ToNumber(Literal(str), Literal(format)).checkInputDataTypes()
      assert(toNumberResult != TypeCheckResult.TypeCheckSuccess,
        s"The format string should have been invalid: $format")
      toNumberResult match {
        case TypeCheckResult.TypeCheckFailure(message) =>
          assert(message.contains(expectedErrMsg))
      }

      val tryToNumberResult = TryToNumber(Literal(str), Literal(format)).checkInputDataTypes()
      assert(tryToNumberResult != TypeCheckResult.TypeCheckSuccess,
        s"The format string should have been invalid: $format")
      tryToNumberResult match {
        case TypeCheckResult.TypeCheckFailure(message) =>
          assert(message.contains(expectedErrMsg))
      }

      val toCharResult = ToCharacter(Decimal(456), Literal(format)).checkInputDataTypes()
      assert(toCharResult != TypeCheckResult.TypeCheckSuccess,
        s"The format string should have been invalid: $format")
      toCharResult match {
        case TypeCheckResult.TypeCheckFailure(message) =>
          assert(message.contains(expectedErrMsg))
      }
    }
  }

  test("ToNumber: negative tests (the input string does not match the format string)") {
    Seq(
      // The input contained more thousands separators than the format string.
      ("45", "0,9"),
      // The input contained more or fewer digits than required.
      ("4", "09"),
      ("454", "09"),
      // The input contained more digits than allowed.
      ("454", "99"),
      // The input string did not contain an expected dollar sign.
      ("45", "$99"),
      // The input string did not contain an expected opening angle bracket.
      ("45>", "99PR"),
      // The input string did not contain an expected closing angle bracket.
      ("<45", "99PR"),
      // The trailing MI did not match against any trailing +.
      ("454+", "999MI"),
      // The trailing PR required exactly one leading < and trailing >.
      ("<454", "999PR"),
      ("454>", "999PR"),
      ("<454 ", "999PR"),
      (" 454>", "999PR"),
      ("<<454>>", "999PR"),
      // At least three digits were required.
      ("45", "S$999,099.99"),
      // Groups of digits with leading zeros are not optional.
      ("$345", "S$099,099.99"),
      // The letter 'D' is allowed in the format string, but not the input string.
      ("4D5", "0D9")
    ).foreach { case (str: String, format: String) =>
      val toNumberExpr = ToNumber(Literal(str), Literal(format))
      assert(toNumberExpr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkExceptionInExpression[IllegalArgumentException](
        toNumberExpr, "does not match the given number format")

      val tryToNumberExpr = TryToNumber(Literal(str), Literal(format))
      assert(tryToNumberExpr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(tryToNumberExpr, null)
    }
  }

  test("ToCharacter: positive tests") {
    // Test '0' and '9'
    Seq(
      (Decimal(454),
        "9999") ->
        " 454",
      (Decimal(454),
        "99999") ->
        "  454",
      (Decimal(4),
        "0") ->
        "4",
      (Decimal(45),
        "00") ->
        "45",
      (Decimal(454),
        "000") ->
        "454",
      (Decimal(454),
        "0000") ->
        "0454",
      (Decimal(454),
        "00000") ->
        "00454"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test '.' and 'D'
    Seq(
      (Decimal(0.4542),
        ".00000") ->
        ".45420",
      (Decimal(454.2),
        "000.0") ->
        "454.2",
      (Decimal(454),
        "000.0") ->
        "454.0",
      (Decimal(454.2),
        "000.00") ->
        "454.20",
      (Decimal(454),
        "000.00") ->
        "454.00",
      (Decimal(0.4542),
        ".0000") ->
        ".4542",
      (Decimal(4542),
        "0000.") ->
        "4542 "
    ).foreach { case ((decimal, format), expected) =>
      val format2 = format.replace('.', 'D')
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)

      expr = ToCharacter(Literal(decimal), Literal(format2))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    Seq(
      (Decimal(454.2),
        "0000.00") ->
        "0454.20",
      (Decimal(454),
        "0000.00") ->
        "0454.00",
      (Decimal(4542),
        "00000.") ->
        "04542 ",
      (Decimal(454.2),
        "9999.99") ->
        " 454.20",
      (Decimal(454),
        "9999.99") ->
        " 454.00",
      // There are no digits after the decimal point.
      (Decimal(4542),
        "99999.") ->
        " 4542 "
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test ',' and 'G'
    Seq(
      (Decimal(12454),
        "0,0000") ->
        "1,2454",
      (Decimal(12454),
        "00,000") ->
        "12,454",
      (Decimal(124543),
        "000,000") ->
        "124,543",
      (Decimal(12),
        "000,000") ->
        "000,012",
      (Decimal(1245436),
        "0,000,000") ->
        "1,245,436",
      (Decimal(12454367),
        "00,000,000") ->
        "12,454,367"
    ).foreach { case ((decimal, format), expected) =>
      val format2 = format.replace(',', 'G')
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)

      expr = ToCharacter(Literal(decimal), Literal(format2))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    Seq(
      (Decimal(12454),
        "000,000") ->
        "012,454",
      (Decimal(12454),
        "00,0000") ->
        "01,2454",
      (Decimal(12454),
        "000,0000") ->
        "001,2454",
      (Decimal(12454),
        "0000,0000") ->
        "0001,2454",
      (Decimal(12454),
        "00,0000") ->
        "01,2454",
      (Decimal(12454),
        "000,0000") ->
        "001,2454",
      (Decimal(12454),
        "0000,0000") ->
        "0001,2454",
      (Decimal(12454367),
        "000,000,000") ->
        "012,454,367",
      (Decimal(12454),
        "999,999") ->
        " 12,454",
      (Decimal(12454),
        "9,9999") ->
        "1,2454",
      (Decimal(12454),
        "99,9999") ->
        " 1,2454",
      (Decimal(12454),
        "999,9999") ->
        "  1,2454",
      (Decimal(12454),
        "9999,9999") ->
        "   1,2454",
      (Decimal(12454367),
        "999,999,999") ->
        " 12,454,367",
      (Decimal(12454),
        "999,999") ->
        " 12,454"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test '$'
    Seq(
      (Decimal(78.12),
        "$99.99") ->
        "$78.12",
      (Decimal(78.12),
        "$00.00") ->
        "$78.12"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test 'S'
    Seq(
      (Decimal(83028485),
        "S99999999999.9999999") ->
        "   +83028485.0000000",
      (Decimal(0),
        "9999999999999999.999999999999999S") ->
        "               0.000000000000000+",
      (Decimal(unscaled = 43100000000L, precision = 38, scale = 10),
        "9999999999999999.999999999999999S") ->
        "               4.310000000000000+",
      (Decimal(-454.8),
        "99G999.9S") ->
        "   454.8-",
      (Decimal(-454.8),
        "00G000.0S") ->
        "00,454.8-",
      (Decimal(-454),
        "S999") ->
        "-454",
      (Decimal(-454),
        "999S") ->
        "454-",
      (Decimal(-12454.8),
        "99G999D9S") ->
        "12,454.8-",
      (Decimal(-83028485),
        "99999999999.9999999S") ->
        "   83028485.0000000-"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test 'MI'
    Seq(
      (Decimal(4.31),
        "9999999999999999.999999999999999MI") ->
        "               4.310000000000000 ",
      (Decimal(0),
        "9999999999999999.999999999999999MI") ->
        "               0.000000000000000 ",
      (Decimal(unscaled = 43100000000L, precision = 38, scale = 10),
        "9999999999999999.999999999999999MI") ->
        "               4.310000000000000 ",
      (Decimal(-454.8),
        "99G999.9MI") ->
        "   454.8-",
      (Decimal(-454.8),
        "00G000.0MI") ->
        "00,454.8-",
      (Decimal(-454),
        "999MI") ->
        "454-",
      (Decimal(-12454.8),
        "99G999D9MI") ->
        "12,454.8-",
      (Decimal(-4.31),
        "MI9999999999999999.999999999999999") ->
        "               -4.310000000000000"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test 'PR'
    Seq(
      (Decimal(4.31),
        "9999999999999999.999999999999999PR") ->
        "               4.310000000000000  ",
      (Decimal(0),
        "9999999999999999.999999999999999PR") ->
        "               0.000000000000000  ",
      (Decimal(unscaled = 43100000000L, precision = 38, scale = 10),
        "9999999999999999.999999999999999PR") ->
        "               4.310000000000000  ",
      (Decimal(-123),
        "9999999999999999.999PR") ->
        "             <123.000>",
      (Decimal(-123.4),
        "9999999999999999.999PR") ->
        "             <123.400>",
      (Decimal(-454.8),
        "99G999.9PR") ->
        "   <454.8>",
      (Decimal(-454.8),
        "00G000.0PR") ->
        "<00,454.8>",
      (Decimal(-454),
        "999PR") ->
        "<454>",
      (Decimal(-12454.8),
        "99G999D9PR") ->
        "<12,454.8>"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }

    // Test overflows
    Seq(
      // If there were more digits in the provided input string (before or after the decimal point)
      // than specified in the format string, an overflow takes place.
      (Decimal(454),
        "0") ->
        "#",
      (Decimal(454),
        "00") ->
        "##",
      (Decimal(4.67),
        "9.9") ->
        "#.#",
      (Decimal(4.67),
        "99.9") ->
        "##.#"
    ).foreach { case ((decimal, format), expected) =>
      var expr: Expression = ToCharacter(Literal(decimal), Literal(format))
      assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess)
      checkEvaluation(expr, expected)
    }
  }

  test("find in set") {
    checkEvaluation(
      FindInSet(Literal.create(null, StringType), Literal.create(null, StringType)), null)
    checkEvaluation(FindInSet(Literal("ab"), Literal.create(null, StringType)), null)
    checkEvaluation(FindInSet(Literal.create(null, StringType), Literal("abc,b,ab,c,def")), null)
    checkEvaluation(FindInSet(Literal("ab"), Literal("abc,b,ab,c,def")), 3)
    checkEvaluation(FindInSet(Literal("abf"), Literal("abc,b,ab,c,def")), 0)
    checkEvaluation(FindInSet(Literal("ab,"), Literal("abc,b,ab,c,def")), 0)
  }

  test("ParseUrl") {
    def checkParseUrl(expected: String, urlStr: String, partToExtract: String): Unit = {
      checkEvaluation(ParseUrl(Seq(urlStr, partToExtract)), expected)
    }
    def checkParseUrlWithKey(
        expected: String,
        urlStr: String,
        partToExtract: String,
        key: String): Unit = {
      checkEvaluation(ParseUrl(Seq(urlStr, partToExtract, key)), expected)
    }

    checkParseUrl("spark.apache.org", "http://spark.apache.org/path?query=1", "HOST")
    checkParseUrl("/path", "http://spark.apache.org/path?query=1", "PATH")
    checkParseUrl("query=1", "http://spark.apache.org/path?query=1", "QUERY")
    checkParseUrl("Ref", "http://spark.apache.org/path?query=1#Ref", "REF")
    checkParseUrl("http", "http://spark.apache.org/path?query=1", "PROTOCOL")
    checkParseUrl("/path?query=1", "http://spark.apache.org/path?query=1", "FILE")
    checkParseUrl("spark.apache.org:8080", "http://spark.apache.org:8080/path?query=1", "AUTHORITY")
    checkParseUrl("userinfo", "http://userinfo@spark.apache.org/path?query=1", "USERINFO")
    checkParseUrlWithKey("1", "http://spark.apache.org/path?query=1", "QUERY", "query")

    // Null checking
    checkParseUrl(null, null, "HOST")
    checkParseUrl(null, "http://spark.apache.org/path?query=1", null)
    checkParseUrl(null, null, null)
    checkParseUrl(null, "test", "HOST")
    checkParseUrl(null, "http://spark.apache.org/path?query=1", "NO")
    checkParseUrl(null, "http://spark.apache.org/path?query=1", "USERINFO")
    checkParseUrlWithKey(null, "http://spark.apache.org/path?query=1", "HOST", "query")
    checkParseUrlWithKey(null, "http://spark.apache.org/path?query=1", "QUERY", "quer")
    checkParseUrlWithKey(null, "http://spark.apache.org/path?query=1", "QUERY", null)
    checkParseUrlWithKey(null, "http://spark.apache.org/path?query=1", "QUERY", "")

    // exceptional cases
    intercept[java.util.regex.PatternSyntaxException] {
      evaluateWithoutCodegen(ParseUrl(Seq(Literal("http://spark.apache.org/path?"),
        Literal("QUERY"), Literal("???"))))
    }

    // arguments checking
    assert(ParseUrl(Seq(Literal("1"))).checkInputDataTypes().isFailure)
    assert(ParseUrl(Seq(Literal("1"), Literal("2"), Literal("3"), Literal("4")))
      .checkInputDataTypes().isFailure)
    assert(ParseUrl(Seq(Literal("1"), Literal(2))).checkInputDataTypes().isFailure)
    assert(ParseUrl(Seq(Literal(1), Literal("2"))).checkInputDataTypes().isFailure)
    assert(ParseUrl(Seq(Literal("1"), Literal("2"), Literal(3))).checkInputDataTypes().isFailure)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(ParseUrl(Seq(Literal("\"quote"), Literal("\"quote"))) :: Nil)
  }

  test("SPARK-33468: ParseUrl in ANSI mode should fail if input string is not a valid url") {
    withSQLConf(SQLConf.ANSI_ENABLED.key -> "true") {
      val msg = intercept[IllegalArgumentException] {
        evaluateWithoutCodegen(
          ParseUrl(Seq("https://a.b.c/index.php?params1=a|b&params2=x", "HOST")))
      }.getMessage
      assert(msg.contains("Find an invalid url string"))
    }
    withSQLConf(SQLConf.ANSI_ENABLED.key -> "false") {
      checkEvaluation(
        ParseUrl(Seq("https://a.b.c/index.php?params1=a|b&params2=x", "HOST")), null)
    }
  }

  test("Sentences") {
    val nullString = Literal.create(null, StringType)
    checkEvaluation(Sentences(nullString, nullString, nullString), null)
    checkEvaluation(Sentences(nullString, nullString), null)
    checkEvaluation(Sentences(nullString), null)
    checkEvaluation(Sentences("", nullString, nullString), Seq.empty)
    checkEvaluation(Sentences("", nullString), Seq.empty)
    checkEvaluation(Sentences(""), Seq.empty)

    val answer = Seq(
      Seq("Hi", "there"),
      Seq("The", "price", "was"),
      Seq("But", "not", "now"))

    checkEvaluation(Sentences("Hi there! The price was $1,234.56.... But, not now."), answer)
    checkEvaluation(Sentences("Hi there! The price was $1,234.56.... But, not now.", "en"), answer)
    checkEvaluation(Sentences("Hi there! The price was $1,234.56.... But, not now.", "en", "US"),
      answer)
    checkEvaluation(Sentences("Hi there! The price was $1,234.56.... But, not now.", "XXX", "YYY"),
      answer)

    // Test escaping of arguments
    GenerateUnsafeProjection.generate(
      Sentences(Literal("\"quote"), Literal("\"quote"), Literal("\"quote")) :: Nil)
  }

  test("SPARK-33386: elt ArrayIndexOutOfBoundsException") {
    Seq(true, false).foreach { ansiEnabled =>
      withSQLConf(SQLConf.ANSI_ENABLED.key -> ansiEnabled.toString) {
        var expr: Expression = Elt(Seq(Literal(4), Literal("123"), Literal("456")))
        if (ansiEnabled) {
          val errMsg = "The index 4 is out of bounds. The array has 2 elements."
          checkExceptionInExpression[Exception](expr, errMsg)
        } else {
          checkEvaluation(expr, null)
        }

        expr = Elt(Seq(Literal(0), Literal("123"), Literal("456")))
        if (ansiEnabled) {
          val errMsg = "The index 0 is out of bounds. The array has 2 elements."
          checkExceptionInExpression[Exception](expr, errMsg)
        } else {
          checkEvaluation(expr, null)
        }

        expr = Elt(Seq(Literal(-1), Literal("123"), Literal("456")))
        if (ansiEnabled) {
          val errMsg = "The index -1 is out of bounds. The array has 2 elements."
          checkExceptionInExpression[Exception](expr, errMsg)
        } else {
          checkEvaluation(expr, null)
        }
      }
    }
  }

  test("SPARK-37508: Support contains string expression") {
    checkEvaluation(Contains(Literal("aa"), Literal.create(null, StringType)), null)
    checkEvaluation(Contains(Literal.create(null, StringType), Literal("aa")), null)
    checkEvaluation(Contains(Literal("Spark SQL"), Literal("Spark")), true)
    checkEvaluation(Contains(Literal("Spark SQL"), Literal("SPARK")), false)
    checkEvaluation(Contains(Literal("Spark SQL"), Literal("SQL")), true)
    checkEvaluation(Contains(Literal("Spark SQL"), Literal("k S")), true)
  }
}


text:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.Http.Description;
using Exceptionless.Api.Extensions;
using Exceptionless.Api.Models;
using Exceptionless.Api.Utility;
using Exceptionless.Core.Authorization;
using Exceptionless.Core.Extensions;
using Exceptionless.Core.Mail;
using Exceptionless.Core.Repositories;
using Exceptionless.Core.Models;
using Exceptionless.DateTimeExtensions;
using FluentValidation;
using Foundatio.Caching;
using Foundatio.Logging;

namespace Exceptionless.Api.Controllers {
    [RoutePrefix(API_PREFIX + "/users")]
    [Authorize(Roles = AuthorizationRoles.User)]
    public class UserController : RepositoryApiController<IUserRepository, User, ViewUser, User, UpdateUser> {
        private readonly IOrganizationRepository _organizationRepository;
        private readonly ICacheClient _cacheClient;
        private readonly IMailer _mailer;

        public UserController(IUserRepository userRepository, IOrganizationRepository organizationRepository, ICacheClient cacheClient, IMailer mailer) : base(userRepository) {
            _organizationRepository = organizationRepository;
            _cacheClient = new ScopedCacheClient(cacheClient, "user");
            _mailer = mailer;
        }

        /// <summary>
        /// Get current user
        /// </summary>
        /// <response code="404">The current user could not be found.</response>
        [HttpGet]
        [Route("me")]
        [ResponseType(typeof(ViewCurrentUser))]
        public async Task<IHttpActionResult> GetCurrentUserAsync() {
            var currentUser = await GetModelAsync(ExceptionlessUser.Id);
            if (currentUser == null)
                return NotFound();

            return Ok(new ViewCurrentUser(currentUser));
        }

        /// <summary>
        /// Get by id
        /// </summary>
        /// <param name="id">The identifier of the user.</param>
        /// <response code="404">The user could not be found.</response>
        [HttpGet]
        [Route("{id:objectid}", Name = "GetUserById")]
        [ResponseType(typeof(ViewUser))]
        public override Task<IHttpActionResult> GetByIdAsync(string id) {
            return base.GetByIdAsync(id);
        }

        /// <summary>
        /// Get by organization
        /// </summary>
        /// <param name="organizationId">The identifier of the organization.</param>
        /// <param name="page">The page parameter is used for pagination. This value must be greater than 0.</param>
        /// <param name="limit">A limit on the number of objects to be returned. Limit can range between 1 and 100 items.</param>
        /// <response code="404">The organization could not be found.</response>
        [HttpGet]
        [Route("~/" + API_PREFIX + "/organizations/{organizationId:objectid}/users")]
        [ResponseType(typeof(List<ViewUser>))]
        public async Task<IHttpActionResult> GetByOrganizationAsync(string organizationId, int page = 1, int limit = 10) {
            if (!CanAccessOrganization(organizationId))
                return NotFound();

            var organization = await _organizationRepository.GetByIdAsync(organizationId, true);
            if (organization == null)
                return NotFound();

            var users = await _repository.GetByOrganizationIdAsync(organizationId);
            var viewUsers = (await MapCollectionAsync<ViewUser>(users.Documents, true)).ToList();
            if (organization.Invites.Any()) {
                viewUsers.AddRange(organization.Invites.Select(i => new ViewUser {
                    EmailAddress = i.EmailAddress,
                    IsInvite = true
                }));
            }

            page = GetPage(page);
            limit = GetLimit(limit);
            return OkWithResourceLinks(viewUsers.Skip(GetSkip(page, limit)).Take(limit).ToList(), viewUsers.Count > limit, page);
        }

        /// <summary>
        /// Update
        /// </summary>
        /// <param name="id">The identifier of the user.</param>
        /// <param name="changes">The changes</param>
        /// <response code="400">An error occurred while updating the user.</response>
        /// <response code="404">The user could not be found.</response>
        [HttpPatch]
        [HttpPut]
        [Route("{id:objectid}")]
        public override Task<IHttpActionResult> PatchAsync(string id, Delta<UpdateUser> changes) {
            return base.PatchAsync(id, changes);
        }

        /// <summary>
        /// Update email address
        /// </summary>
        /// <param name="id">The identifier of the user.</param>
        /// <param name="email">The new email address.</param>
        /// <response code="400">An error occurred while updating the users email address.</response>
        /// <response code="404">The user could not be found.</response>
        [HttpPost]
        [Route("{id:objectid}/email-address/{email:minlength(1)}")]
        [ResponseType(typeof(UpdateEmailAddressResult))]
        public async Task<IHttpActionResult> UpdateEmailAddressAsync(string id, string email) {
            var user = await GetModelAsync(id, false);
            if (user == null)
                return NotFound();

            email = email.ToLower();
            if (String.Equals(ExceptionlessUser.EmailAddress, email, StringComparison.OrdinalIgnoreCase))
                return Ok(new UpdateEmailAddressResult { IsVerified = user.IsEmailAddressVerified });

            // Only allow 3 email address updates per hour period by a single user.
            string updateEmailAddressAttemptsCacheKey = $"{ExceptionlessUser.Id}:attempts";
            long attempts = await _cacheClient.IncrementAsync(updateEmailAddressAttemptsCacheKey, 1, DateTime.UtcNow.Ceiling(TimeSpan.FromHours(1)));
            if (attempts > 3)
                return BadRequest("Update email address rate limit reached. Please try updating later.");

            if (!await IsEmailAddressAvailableInternalAsync(email))
                return BadRequest("A user with this email address already exists.");

            user.ResetPasswordResetToken();
            user.EmailAddress = email;
            user.IsEmailAddressVerified = user.OAuthAccounts.Count(oa => String.Equals(oa.EmailAddress(), email, StringComparison.OrdinalIgnoreCase)) > 0;
            if (!user.IsEmailAddressVerified)
                user.CreateVerifyEmailAddressToken();
            else
                user.ResetVerifyEmailAddressToken();

            try {
                await _repository.SaveAsync(user, true);
            } catch (ValidationException ex) {
                return BadRequest(String.Join(", ", ex.Errors));
            } catch (Exception ex) {
                Logger.Error().Exception(ex).Property("User", user).SetActionContext(ActionContext).Write();
                return BadRequest("An error occurred.");
            }

            if (!user.IsEmailAddressVerified)
                await ResendVerificationEmailAsync(id);

            return Ok(new UpdateEmailAddressResult { IsVerified = user.IsEmailAddressVerified });
        }

        /// <summary>
        /// Verify email address
        /// </summary>
        /// <param name="token">The token identifier.</param>
        /// <response code="400">Verify Email Address Token has expired.</response>
        /// <response code="404">The user could not be found.</response>
        [HttpGet]
        [Route("verify-email-address/{token:token}")]
        public async Task<IHttpActionResult> VerifyAsync(string token) {
            var user = await _repository.GetByVerifyEmailAddressTokenAsync(token);
            if (user == null) {
                // The user may already be logged in and verified.
                if (ExceptionlessUser != null && ExceptionlessUser.IsEmailAddressVerified)
                    return Ok();

                return NotFound();
            }

            if (!user.HasValidVerifyEmailAddressTokenExpiration())
                return BadRequest("Verify Email Address Token has expired.");

            user.MarkEmailAddressVerified();
            await _repository.SaveAsync(user, true);

            //ExceptionlessClient.Default.CreateFeatureUsage("Verify Email Address").AddObject(user).Submit();
            return Ok();
        }

        /// <summary>
        /// Resend verification email
        /// </summary>
        /// <param name="id">The identifier of the user.</param>
        /// <response code="404">The user could not be found.</response>
        [HttpGet]
        [Route("{id:objectid}/resend-verification-email")]
        public async Task<IHttpActionResult> ResendVerificationEmailAsync(string id) {
            var user = await GetModelAsync(id, false);
            if (user == null)
                return NotFound();

            if (!user.IsEmailAddressVerified) {
                user.CreateVerifyEmailAddressToken();
                await _repository.SaveAsync(user, true);
                await _mailer.SendVerifyEmailAsync(user);
            }

            return Ok();
        }

        [HttpPost]
        [Route("{id:objectid}/admin-role")]
        [OverrideAuthorization]
        [Authorize(Roles = AuthorizationRoles.GlobalAdmin)]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<IHttpActionResult> AddAdminRoleAsync(string id) {
            var user = await GetModelAsync(id, false);
            if (user == null)
                return NotFound();

            if (!user.Roles.Contains(AuthorizationRoles.GlobalAdmin)) {
                user.Roles.Add(AuthorizationRoles.GlobalAdmin);
                await _repository.SaveAsync(user, true);
            }

            return Ok();
        }

        [HttpDelete]
        [Route("{id:objectid}/admin-role")]
        [OverrideAuthorization]
        [Authorize(Roles = AuthorizationRoles.GlobalAdmin)]
        [ApiExplorerSettings(IgnoreApi = true)]
        public async Task<IHttpActionResult> DeleteAdminRoleAsync(string id) {
            var user = await GetModelAsync(id, false);
            if (user == null)
                return NotFound();

            if (user.Roles.Contains(AuthorizationRoles.GlobalAdmin)) {
                user.Roles.Remove(AuthorizationRoles.GlobalAdmin);
                await _repository.SaveAsync(user, true);
            }

            return StatusCode(HttpStatusCode.NoContent);
        }

        private async Task<bool> IsEmailAddressAvailableInternalAsync(string email) {
            if (String.IsNullOrWhiteSpace(email))
                return false;

            if (ExceptionlessUser != null && String.Equals(ExceptionlessUser.EmailAddress, email, StringComparison.OrdinalIgnoreCase))
                return true;

            return await _repository.GetByEmailAddressAsync(email) == null;
        }

        protected override async Task<User> GetModelAsync(string id, bool useCache = true) {
            if (Request.IsGlobalAdmin() || String.Equals(ExceptionlessUser.Id, id))
                return await base.GetModelAsync(id, useCache);

            return null;
        }

        protected override Task<ICollection<User>> GetModelsAsync(string[] ids, bool useCache = true) {
            if (Request.IsGlobalAdmin())
                return base.GetModelsAsync(ids, useCache);

            return base.GetModelsAsync(ids.Where(id => String.Equals(ExceptionlessUser.Id, id)).ToArray(), useCache);
        }
    }
}


text:
using System;
using System.Collections.Generic;
using System.Text;
using SharpMap.CoordinateSystems.Transformations;
using SharpMap.CoordinateSystems;
using SharpMap.Layers;

namespace Ptv.Controls.Map.Interface
{
    /// <summary>
    /// Interface for accessing SharpMap
    /// </summary>
    public interface ISharpMapContainer
    {
        /// <summary>
        /// Gets the SharpMap instance for rendering overlays
        /// </summary>
        SharpMap.Map SharpMap
        {
            get;
        }

        /// <summary>
        /// refreshes the SharpMap overlay
        /// </summary>
        void SharpMapRefresh();

        void InsertLayer(ILayer layer, int zOrder);

        void InsertLayer(ILayer layer, int zOrder, IDawnLayer owner);

        List<LayerToolTips> GetQuickInfos(System.Drawing.Point p);

        SharpMap.Map[] SharpMaps
        {
            get;
        }

        List<DawnLayer> RootLayers
        {
            get;
        }
    }

    public class LayerToolTips
    {
        public System.Drawing.Image Bitmap;
        public string Caption;
        private System.Collections.Generic.Dictionary<object, object> _Ids = new Dictionary<object, object>();

        public void AddToolTipInfo(ToolTipInfo info)
        {
            if (info.Id != null && _Ids.ContainsKey(info.Id))
                return;

            if (info.Id != null)
                _Ids[info.Id] = info.Id;

            ToolTips.Add(info);
        }

        public List<ToolTipInfo> ToolTips = new List<ToolTipInfo>();
    }

    public class ToolTipInfo
    {
        public string Description;
        public System.Drawing.Image Bitmap;
        public object Id;
    }
}