includes :assert :seq

add_results setup name: "seq tests" {
  nums = seq.new { n | n + 1} 0

  test "seq get" {
    m = my
    10.times { i |
      m.assert_equal i, { nums[i] }
    }
  }

  test "seq map then get" {
    s = nums.map({ n | n * 2 })
    assert_equal 0 { s[0] }
    assert_equal 0 { s[0] }
    assert_equal 2 { s[1] }
    assert_equal 4 { s[2] }
  }

  test "seq map get empty" {
    s = seq.new({ seq.stop }).map({ n | n * 2 })
    assert_null s[0]
    assert_null s[1]
  }

  test "seq take" {
    assert_equal seq, { nums.take(5).parent }
    assert_equal 5, { nums.take(5).to_array.length }
    assert_equal 0, { nums.take(0).to_array.length }
  }

  test "seq map with block" {
    s = nums.map({ x | x * x })

    assert_equal seq, { s.parent }
    assert_equal 0 { s[0] }
    assert_equal 0 { s[0] }
    assert_equal [0, 1, 4, 9, 16] { s.take(5).to_array }
    assert_equal [0, 1, 4, 9, 16] { s.take(5).to_array }
  }

  test "seq map with name" {
    s = nums.map(:to_s)

    assert_equal 0.to(10).map(:to_s) { s.take(11).to_array }
    assert { s.take(10).to_array.all? { n | n.string? } }
  }

  test "empty seq map" {
    assert_equal [] { nums.take(0).map({ x | x + 1 }).to_array }
  }

  test "seq select with block" {
    assert_equal [0 2 4 6 8] { nums.select({ n | n % 2 == 0 }).take(5).to_array }
  }

  test "seq select with name" {
    number.odd? = { my % 2 == 1 }

    assert_equal [1 3 5 7 9] { nums.select(:odd?).take(5).to_array }
  }

  test "seq reject with block" {
    assert_equal [1 3 5 7 9] { nums.reject({ n | n % 2 == 0 }).take(5).to_array }
  }

  test "seq reject with name" {
    number.odd? = { my % 2 == 1 }

    assert_equal [0 2 4 6 8] { nums.reject(:odd?).take(5).to_array }
  }


  test "seq.any?" {
    s = nums.take 5

    assert { nums.any? { x | x > 10 } }
    assert_false { s.any? { x | x < 0 } }
  }

  test "seq.all?" {
    s = nums.take 5

    assert { s.all? { x | x < 5 } }
    assert_false { nums.all? { x | x < 5 } }
  }

  test "seq.find" {
    s = nums.take 5

    assert_equal 11, { nums.find { x | x > 10 } }
    assert_null { s.find { x | x < 0 } }
  }

  test "seq.last" {
    s = nums.take 5

    assert_equal 4 { s.last }
    assert_null { seq.new({ seq.stop }).last }
  }

  test "seq.count" {
    assert_equal 0 { seq.new({ seq.stop }).count }
    assert_equal 5 { nums.take(5).count }
  }

  test "array.to_seq" {
    a = [1 2 3 4 5]
    assert_equal a, { a.to_seq.to_array }
    assert_equal [2 4 6] { a.to_seq.map({ n | n * 2 }).take(3).to_array }
  }

  test "seq.take_while" {
    a = [0 1 2 3 4]

    assert_equal a, { nums.take_while({ n | n < 5 }).to_array }
    assert_equal a, { a.to_seq.take_while({ n | n < 10 }).to_array }
    assert_equal [] { nums.take_while({ n | n < 0 }).to_array }
  }

  test "seq.drop_while" {
    a = [5 6 7 8 9]

    assert_equal a, { nums.drop_while({ n | n < 5 }).take(5).to_array }
    assert_equal [] { [1 2 3].to_seq.drop_while({ n | n < 5 }).take(5).to_array }
  }

  test "seq.reduce" {
    assert_equal 0 { nums.take(0).reduce(0, :+) }
    assert_equal null, { nums.take(0).reduce(:+) }
    assert_equal 10 { nums.take(5).reduce(:+) }
    assert_equal 10 { nums.take(5).reduce(0, :+) }
    assert_equal 10 { nums.take(5).reduce(0, { m, i | m + i }) }
    assert_equal 10 { nums.take(5).reduce({ m, i | m + i }) }
  }
}