/**
 * Unit tests for set strategies
 */
module sets-test
imports libstratego-lib
strategies

  main = 
    test-suite(!"Testsuite for IndexedSets",
        test-create
      ; test-add
      ; test-remove
      ; test-clear
      ; test-elements
      ; test-fixpoint
    )

strategies

  test-create =
    apply-and-check(!"new iset", new-iset, !(), ?IndexedSet(_); iset-destroy)

  test-add =
      iset-apply-and-check(!"iset add"
      , iset-add(|1)
      , iset-contains(|1)
      )
    ; iset-apply-and-check(!"iset two elements"
      , iset-add(|1)
        ; iset-add(|2)
      , iset-contains(|1)
        ; iset-contains(|2)
      )
    ; iset-apply-and-check(!"iset add two identical elements (1)"
      , iset-add(|1)
        ; iset-add(|1)
      , iset-contains(|1)
      )
    ; iset-apply-test(!"iset add two identical elements (2)"
      , iset-add(|1)
        ; iset-add(|1)
        ; iset-elements
      | [1]
      )

  test-remove =
      iset-apply-and-check(!"iset remove"
      , iset-remove(|1)
      , iset-add(|1)
      , not(iset-contains(|1))
      )
    ; iset-apply-and-check(!"iset remove 2"
      , iset-remove(|1)
      , iset-add(|1)
        ; iset-add(|2)
      , not(iset-contains(|1))
        ; iset-contains(|2)
      )

  test-clear =
      iset-apply-test(!"iset clear 1"
      , iset-clear; iset-elements
      , iset-add(|1)
        ; iset-add(|2)
      | []
      )
    ; iset-apply-test(!"iset clear 2"
      , iset-clear; iset-add(|3); iset-elements
      , iset-add(|1)
        ; iset-add(|2)
      | [3]
      )

  test-elements = 
      iset-apply-test(!"iset elements (1)"
      , iset-elements; qsort(lt)
      , iset-add(|1)
        ; iset-add(|2)
      | [1, 2]
      )
    ; iset-apply-test(!"iset elements (2)"
      , iset-elements; qsort(lt)
      , iset-add(|1)
        ; iset-add(|2)
        ; iset-add(|3)
        ; iset-remove(|2)
        ; iset-add(|4)
      | [1, 3, 4]
      )

  test-fixpoint =
    iset-apply-test(!"iset-fixpoint 1"
    , iset-fixpoint(FixPointHelper)
      ; iset-elements
    , iset-add(|1)
    | [1, 2, 3, 4]
    )
  ; iset-apply-test(!"iset-fixpoint 2"
    , iset-fixpoint(FixPointHelper)
      ; iset-elements
    , iset-add(|1)
      ; iset-add(|2)
      ; iset-add(|3)
      ; iset-add(|4)
    | [1, 2, 3, 4]
    )
  ; iset-apply-test(!"iset-fixpoint 3"
    , iset-fixpoint(FixPointHelper)
      ; iset-elements
    , id
    | []
    )
  ; iset-apply-test(!"iset-fixpoint 4"
    , iset-fixpoint(FixPointHelper)
      ; iset-elements
    , iset-add(|5)
    | [5]
    )

  FixPointHelper : 1 -> [2, 3]
  FixPointHelper : 3 -> [4]

/**
 * Test abstractions
 */
strategies

  iset-apply-and-check(name, s, check) =
    iset-apply-and-check(name, id, s, check)

  iset-apply-and-check(name, s, init, check) =
      where(new-iset => set)
    ; apply-and-check(name, s, <init> set, check)
    ; where(<iset-destroy> set)

  iset-apply-test(name, s | check) =
    iset-apply-test(name, id, s | check)

  iset-apply-test(name, s, init | check) =
      where(new-iset => set)
    ; apply-test(name, s, <init> set, !check)
    ; where(<iset-destroy> set)


