sapphire-lang 0.8.0

Gradually typed scripting language where every value is an object and types are optional, checked at runtime
Documentation
class SetTest < Test {
  def test_new_empty_set {
    s = Set.new
    assert_equal(0, s.size)
    assert(s.empty?)
  }

  def test_new_from_list {
    s = Set.new([1, 2, 3])
    assert_equal(3, s.size)
    assert(s.include?(1))
    assert(s.include?(2))
    assert(s.include?(3))
  }

  def test_new_from_list_deduplicates {
    s = Set.new([1, 2, 2, 3, 1])
    assert_equal(3, s.size)
  }

  def test_include_true_for_member {
    s = Set.new([10, 20])
    assert(s.include?(10))
    assert(s.include?(20))
  }

  def test_include_false_for_non_member {
    s = Set.new([10, 20])
    assert(!s.include?(99))
  }

  def test_add_new_element_increases_size {
    s = Set.new
    s.add(1)
    s.add(2)
    assert_equal(2, s.size)
  }

  def test_add_duplicate_does_not_increase_size {
    s = Set.new([1, 2])
    s.add(1)
    assert_equal(2, s.size)
  }

  def test_add_returns_self {
    s = Set.new
    result = s.add(1)
    assert_equal(1, result.size)
  }

  def test_delete_removes_element {
    s = Set.new([1, 2, 3])
    s.delete(2)
    assert_equal(2, s.size)
    assert(!s.include?(2))
    assert(s.include?(1))
    assert(s.include?(3))
  }

  def test_delete_missing_element_is_noop {
    s = Set.new([1, 2])
    s.delete(99)
    assert_equal(2, s.size)
  }

  def test_to_a_returns_list {
    s = Set.new([3, 1, 2])
    a = s.to_a
    assert_equal(3, a.size)
    assert(a.include?(1))
    assert(a.include?(2))
    assert(a.include?(3))
  }

  def test_to_s_single_element {
    s = Set.new([1])
    assert_equal("Set{1}", s.to_s)
  }

  def test_to_s_empty_set {
    s = Set.new
    assert_equal("Set{}", s.to_s)
  }

  def test_union_combines_elements {
    a = Set.new([1, 2])
    b = Set.new([2, 3])
    u = a.union(b)
    assert_equal(3, u.size)
    assert(u.include?(1))
    assert(u.include?(2))
    assert(u.include?(3))
  }

  def test_union_does_not_mutate_self {
    a = Set.new([1, 2])
    b = Set.new([3])
    a.union(b)
    assert_equal(2, a.size)
  }

  def test_intersection_keeps_shared_elements {
    a = Set.new([1, 2, 3])
    b = Set.new([2, 3, 4])
    i = a.intersection(b)
    assert_equal(2, i.size)
    assert(i.include?(2))
    assert(i.include?(3))
    assert(!i.include?(1))
  }

  def test_intersection_empty_when_disjoint {
    a = Set.new([1, 2])
    b = Set.new([3, 4])
    assert_equal(0, a.intersection(b).size)
  }

  def test_difference_removes_shared_elements {
    a = Set.new([1, 2, 3])
    b = Set.new([2, 3])
    d = a.difference(b)
    assert_equal(1, d.size)
    assert(d.include?(1))
  }

  def test_difference_empty_when_subset {
    a = Set.new([1, 2])
    b = Set.new([1, 2, 3])
    assert_equal(0, a.difference(b).size)
  }

  def test_subset_true {
    a = Set.new([1, 2])
    b = Set.new([1, 2, 3])
    assert(a.subset?(b))
  }

  def test_subset_false {
    a = Set.new([1, 4])
    b = Set.new([1, 2, 3])
    assert(!a.subset?(b))
  }

  def test_subset_empty_set_is_subset_of_anything {
    assert(Set.new.subset?(Set.new([1, 2])))
  }

  def test_superset_true {
    a = Set.new([1, 2, 3])
    b = Set.new([1, 2])
    assert(a.superset?(b))
  }

  def test_superset_false {
    a = Set.new([1, 2])
    b = Set.new([1, 2, 3])
    assert(!a.superset?(b))
  }

  def test_disjoint_true {
    a = Set.new([1, 2])
    b = Set.new([3, 4])
    assert(a.disjoint?(b))
  }

  def test_disjoint_false {
    a = Set.new([1, 2])
    b = Set.new([2, 3])
    assert(!a.disjoint?(b))
  }

  def test_each_yields_all_elements {
    s = Set.new([10, 20, 30])
    sum = 0
    s.each { |x| sum = sum + x }
    assert_equal(60, sum)
  }

  def test_map_transforms_to_list {
    s = Set.new([1, 2, 3])
    result = s.map { |x| x * 2 }
    assert_equal(3, result.size)
    assert(result.include?(2))
    assert(result.include?(4))
    assert(result.include?(6))
  }

  def test_select_returns_set_of_matching {
    s = Set.new([1, 2, 3, 4])
    result = s.select { |x| x > 2 }
    assert_equal(2, result.size)
    assert(result.include?(3))
    assert(result.include?(4))
  }

  def test_reject_excludes_matching {
    s = Set.new([1, 2, 3])
    result = s.reject { |x| x == 2 }
    assert_equal(2, result.size)
    assert(!result.include?(2))
  }

  def test_any_true_when_one_matches {
    s = Set.new([1, 2, 3])
    assert(s.any? { |x| x > 2 })
  }

  def test_any_false_when_none_match {
    s = Set.new([1, 2, 3])
    assert(!s.any? { |x| x > 9 })
  }

  def test_all_true_when_all_match {
    s = Set.new([1, 2, 3])
    assert(s.all? { |x| x > 0 })
  }

  def test_all_false_when_one_fails {
    s = Set.new([1, 2, 3])
    assert(!s.all? { |x| x > 2 })
  }

  def test_none_true_when_none_match {
    s = Set.new([1, 2, 3])
    assert(s.none? { |x| x > 9 })
  }

  def test_none_false_when_one_matches {
    s = Set.new([1, 2, 3])
    assert(!s.none? { |x| x > 2 })
  }

  def test_each_with_index_yields_indices {
    s = Set.new(["a", "b", "c"])
    indices = []
    s.each_with_index { |item, i| indices.append(i) }
    assert_equal(0, indices[0])
    assert_equal(1, indices[1])
    assert_equal(2, indices[2])
  }

  def test_set_operations_do_not_mutate_self {
    a = Set.new([1, 2, 3])
    b = Set.new([3, 4])
    a.union(b)
    a.intersection(b)
    a.difference(b)
    assert_equal(3, a.size)
  }
}