include :assert

add_results setup name: "string tests" {
  test "string.alpha?" {
    assert { "hello".alpha? }
    assert { "h".alpha? }
    assert_false { "123".alpha? }
    assert_false { "".alpha? }
    assert_false { "abc!cba".alpha? }
  }

  test "string.alphanum?" {
    assert { "hello".alphanum? }
    assert { "h".alphanum? }
    assert { "123".alphanum? }
    assert { "1abc123cba1".alphanum? }
    assert_false { "".alphanum? }
    assert_false { "abc!cba".alphanum? }
  }

  test "string.numeric?" {
    assert { "-10".numeric? } 
    assert { "1".numeric? }
    assert { "12381723123".numeric? }
    assert_false { "hello".numeric? }
    assert_false { "1  2".numeric? }
    assert_false { "1123abc13123".numeric? }
    assert_false { "".numeric? }
  }

  test "string.blank?" {
    assert { "".blank? }
    assert { " ".blank? }
    assert { "\t".blank? }
    assert { "\n".blank? }
    assert { " \t \n    ".blank? }
  }

  test "string_chomp" {
    assert_equal "hello" { "hello\n".chomp }
    assert_equal "hello" { "hello\r\n".chomp }
    assert_equal "hello" { "hello\n\r\n".chomp }
  }

  test "string_chomp!" {
    assert_equal "hello" { "hello\n".chomp! }
    assert_equal "hello" { a = "hello\r\n"; a.chomp! }
    assert_equal "hello" { a = "hello\n\r\n"; a.chomp!; a }
  }

  test "string.dice" {
    assert_equal [:a :b :c] { "abc".dice }
    assert_equal [] { "".dice }
    assert_equal [:h :e :l :l :o] { "hello".dice }
  }

  test "string_strip" {
    assert_equal "hello" { ' hello '.strip }
    assert_equal "hel lo" { ' hel lo '.strip }
    assert_equal "hel lo" { "\n hel lo\n\t ".strip }
    assert_equal 12 { a = "\n hel lo \n\t "; a.strip; a.length }
  }

  test "string_strip!" {
    assert_equal "hello" { ' hello '.strip! }
    assert_equal "hel lo" { a = ' hel lo '.strip!; a }
    assert_equal "hel lo" { a = "\n hel lo\n\t "; a.strip!; a }
    assert_equal 6 { a = "\n hel lo\n\t "; a.strip!; a.length }
  }

  test "string_split" {
    assert_equal [:he, :o], { "hello".split "l" }
    assert_equal [:h, :llo], { "hello".split "e" }
    assert_equal [:hello], { "hello".split "z" }
    assert_equal [:hello], { "hello".split }
    assert_equal [], { "hello".split "hello" }
    assert_equal [], { "".split "hello" }
    assert_equal [:h :e :l :l :o], { "hello".split "" }
  }

  test "string_reverse" {
    assert_equal "dcba" { 'abcd'.reverse }
    assert_equal "abcd" { 'abcd'.reverse.reverse }
    assert_equal "abcd" { a = 'abcd'; a.reverse;a }
  }

  test "string_reverse!" {
    assert_equal "dcba" { 'abcd'.reverse! }
    assert_equal "abcd" { 'abcd'.reverse!.reverse! }
    assert_equal "dcba" { a = 'abcd'; a.reverse!;a }
  }

  test "string" {
    assert_equal "a" { "a" }
    assert_equal 1 { a = "a"; b = [a : 1]; b["a"] }
  }

  test "string_downcase" {
    assert_equal "hello!" { 'HELLO!'.downcase }
    assert_equal "hello!" { a = 'HELLO!'; a.downcase!; a }
    assert_equal "HELLO!" { a = 'HELLO!'; a.downcase; a }
  }

  test "string_upcase" {
    assert_equal "HELLO!" { 'hElLo!'.upcase }
    assert_equal "HELLO!" { a = 'heLlO!'; a.upcase!; a }
    assert_equal "hello!" { a = 'hello!'; a.upcase; a }
  }

  test "string_interpolation" {
    assert_equal "abc" { "a#{"b"}c" }
    assert_equal "abc" { "a#{  "b"  }c" }
    assert_equal "abc" { "a#{  "b" ;  }c" }
    assert_equal "abc" { f = { "b" }; "a#{ f }c" }
    assert_equal "abc" { f = { "c" }; "a#{ f; "b" }c" }
    assert_equal "abc" { f = { "c" }; c = "c"; "#{"a"}#{ f; "b" }#{ c }" }
    assert_equal "a-b c" { f = { "c" }; c = "c"; "#{"a"}-#{ f; "b" } #{ c }" }
    assert_equal "a-b c" { f = { "c" }; b = null; c = null; a = { b = { c = "c"; "b" }; "a" }; "#{a}-#{ f; b } #{ c }" }
  }

  test "string_indexing" {
    assert_equal "b" { b = "abc"; b[1] }
    assert_equal "abc" { "zabcdef"[1,3] }
    assert_equal "abc" { "zabcdef"[-6,-4] }
    assert_equal "ef" { "zabcdef"[10,5] }
  }

  test "string_sub_special" {
    assert_equal "helloworld" { '  he llo   w orl d  '.sub /\s/ '' }
    assert_equal "hello world",  { "he  l  l  o w  or  ld".sub(/\s{2,}/, "") }
    assert_equal "wello world",  { "hello world".sub(/^\w/, "w") }
  }

  test "string_sub" {
    assert_equal "b" { "a".sub /a/, "b" }
    assert_equal "axdx" { "acdc".sub /c/, "x" }
    assert_equal "hewo worwd" { "hello world".sub /l+/, "w" }
    assert_equal "hewo worwd" { a = "hello world"; a.sub /l+/, "w" }
    assert_equal 10 { a = "hello world"; a.sub!(/l+/, "w").length }
    assert_equal "hecko world" { a = "hello world"; a.sub /hell/, { m | "heck" } }
    assert_equal "chaaxa" { a = "cheese"; a.sub /(e|s)/, { m | true? m == "s", "x", "a" } }
    assert_equal "cheese" { a = "cheese"; a.sub /(e|s)/, { m | true? m == "s", "x", "a" }; a }
  }

  test "string_sub!" {
    assert_equal "b" { "a".sub! /a/, "b" }
    assert_equal "axdx" { a = "acdc"; a.sub! /c/, "x"; a }
    assert_equal "hewo worwd" { "hello world".sub! /l+/, "w" }
    assert_equal "hewo worwd" { a = "hello world"; a.sub! /l+/, "w"; a }
    assert_equal 10 { a = "hello world"; a.sub! /l+/, "w"; a.length }
    assert_equal "hecko world" { a = "hello world"; a.sub! /hell/, { m | "heck" } }
    assert_equal "chaaxa" { a = "cheese"; a.sub! /(e|s)/, { m | true? m == "s", "x", "a" } }
    assert_equal "chaaxa" { a = "cheese"; a.sub! /(e|s)/, { m | true? m == "s", "x", "a" }; a }
  }

  test "string_sub_first" {
    assert_equal "b" { "a".sub_first /a/, "b" }
    assert_equal "axdc" { "acdc".sub_first /c/, "x" }
    assert_equal "hewo world" { "hello world".sub_first /l+/, "w" }
    assert_equal "hewo world" { a = "hello world"; a.sub_first /l+/, "w" }
    assert_equal "hello world" { a = "hello world"; a.sub_first /l+/, "w"; a }
    assert_equal 10 { a = "hello world"; b = a.sub_first /l+/, "w"; b.length }
  }

  test "string_sub_first!" {
    assert_equal "b" { "a".sub_first! /a/, "b" }
    assert_equal "axdc" { "acdc".sub_first! /c/, "x" }
    assert_equal "hewo world" { "hello world".sub_first! /l+/, "w" }
    assert_equal "hewo world" { a = "hello world"; a.sub_first! /l+/, "w" }
    assert_equal "hewo world" { a = "hello world"; a.sub_first! /l+/, "w"; a }
    assert_equal 10 { a = "hello world"; a.sub_first! /l+/, "w"; a.length }
  }

  test "string_set" {
    assert_equal 'b' { a = "abcde"; a[3] = "b"; a[3] }
    assert_equal 'b' { a = "abcde"; a[-3] = "b"; a[2] }
  }

  test "string_add" {
    assert_equal "abcd" { "a" + "b" + "c" + "d" }
    assert_equal "a" { a = "a"; a + "b" + "c" + "d"; a }
    assert_equal 4 { c = "a" + "b" + "c" + "d"; c.length }
  }

  test "string_concat" {
    assert_equal "abcd" { "a" << "b" << "c" << "d" }
    assert_equal "abcd" { a = "a"; a << "b" << "c" << "d"; a }
    assert_equal 4 { a = "a"; a << "b" << "c" << "d"; a.length }
  }

  test "string_multiply" {
    assert_equal "aaaa" { "a" * 4 }
    assert_equal 40 { ("a" * 40).length }
    assert_equal 0 { ("a" * 0).length }
  }

  test "string_to_f" {
    assert_equal 0.5 { "0.5".to_f }
    assert_equal 1.5 { 1 + "0.5".to_f }
    assert_equal 10000000000000 { "10000000000000".to_f }
  }

  test "string_to_i" {
    assert_equal 0 { "0.5".to_i }
    assert_equal 2 { 1 + "1.5".to_i }
    assert_equal 10000000000000 { "10000000000000".to_i }
  }

  test "string.to_byte" {
    assert_equal 97 { "a".to_byte }
    assert_equal [97 98 99] { "abc".to_byte }
    assert_equal "!" { "!".to_byte.to_char }
  }

  test "string_compare" {
    assert { a = "hello!"; b = "hello!"; a == b }
    assert_false { "\'ello, mate" == "sup?" }
    assert { "a" < "b" }
    assert { "b" >= "a" }
    assert { "a" <= "b" }
    assert_false { "a" == 1 }
  }

  test "string.include?" {
    assert { "blah blah blah".include? :blah }
    assert { "blah blah blah".include? /(blah ?){3}/ }
    assert_false { "blah blah blah".include? :blarg }
    assert_false { "blah blah blah".include? /(blah ?){4}/ }
  }

  test "string.each" {
    assert_equal "hello" { a = []; "hello".each { s | a << s }; a.join }
  }

  test "string.reverse_each" {
    assert_equal "olleh" { a = []; "hello".reverse_each { s | a << s }; a.join }
  }

  test "string.each_line" {
    x = null
    "".each_line { l | assert false }
    "1".each_line { l | x = l }
    assert_equal "1", x
    "\n".each_line { l | x = l }
    assert_equal "" x
  }

  test "string.each_line without a block" {
    assert_equal "a\nb\nc\nd\ne".each_line, [:a :b :c :d :e]
  }
}