# -*- tcl -*-
# finite_automaton.test:  tests for the grammar::fa container.
#
# Copyright (c) 2004 by Andreas Kupries <andreas_kupries@users.sourceforge.net>
#
# RCS: @(#) $Id: fa_state.test,v 1.2 2004/04/04 19:51:24 andreas_kupries Exp $

# -------------------------------------------------------------------------

test fa-state-1.0 {state, error} {
    grammar::fa a
    catch {a state} res
    a destroy
    set res
} {wrong # args: should be "::grammar::fa::Snit_methodstate type selfns win self cmd s args"}


test fa-state-1.1 {state, error} {
    grammar::fa a
    catch {a state add} res
    a destroy
    set res
} {wrong # args: should be "::grammar::fa::Snit_methodstate type selfns win self cmd s args"}


test fa-state-1.2 {state, error} {
    grammar::fa a
    a state add x
    catch {a state foo x} res
    a destroy
    set res
} {Expected add, exists, delete, or rename, got "foo"}


test fa-state-1.3 {state, error} {
    grammar::fa a
    a state add x
    catch {a state add x} res
    a destroy
    set res
} {State "x" is already known}


test fa-state-1.4 {state, error} {
    grammar::fa a
    catch {a state exists} res
    a destroy
    set res
} {wrong # args: should be "::grammar::fa::Snit_methodstate type selfns win self cmd s args"}


test fa-state-1.5 {state, error} {
    grammar::fa a
    catch {a state exists a b} res
    a destroy
    set res
} {wrong#args: ::a state exists s}


test fa-state-1.6 {state, error} {
    grammar::fa a
    catch {a state delete} res
    a destroy
    set res
} {wrong # args: should be "::grammar::fa::Snit_methodstate type selfns win self cmd s args"}


test fa-state-1.7 {state, error} {
    grammar::fa a
    catch {a state delete x} res
    a destroy
    set res
} {Illegal state "x"}


test fa-state-1.8 {state, error} {
    grammar::fa a
    catch {a state rename} res
    a destroy
    set res
} {wrong # args: should be "::grammar::fa::Snit_methodstate type selfns win self cmd s args"}


test fa-state-1.9 {state, error} {
    grammar::fa a
    catch {a state rename foo} res
    a destroy
    set res
} {wrong#args: ::a state rename s s'}


test fa-state-1.10 {state, error} {
    grammar::fa a
    catch {a state rename x y} res
    a destroy
    set res
} {Illegal state "x"}


test fa-state-1.11 {state, error} {
    grammar::fa a
    a state add x y
    catch {a state rename x y} res
    a destroy
    set res
} {State "y" is already known}


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


test fa-state-2.0 {state add} {
    grammar::fa a
    set res [a state add x]
    a destroy
    set res
} {}


test fa-state-2.1 {state add, variadic} {
    grammar::fa a
    set res [a state add x y]
    a destroy
    set res
} {}


test fa-state-2.2 {state add / states / exists} {
    grammar::fa a
    a state add x
    set     res [a states]
    lappend res [a state exists x]
    lappend res [a state exists y]
    a destroy
    set res
} {x 1 0}


test fa-state-2.3 {state add / states / exists} {
    grammar::fa a
    a state add x y
    set res {}
    lappend res [lsort [a states]]
    lappend res [a state exists x]
    lappend res [a state exists y]
    a destroy
    set res
} {{x y} 1 1}


test fa-state-2.4 {state add, basic properties} {
    grammar::fa a
    a state add x
    set res {}
    lappend res [a final?   x]
    lappend res [a start?   x]
    lappend res [a symbols@ x]
    a destroy
    set res
} {0 0 {}}


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

test fa-state-3.0 {state delete} {
    grammar::fa a
    a state add x
    set     res [a states]
    lappend res [a state exists x]
    a state delete x
    lappend res [a states]
    lappend res [a state exists x]
    a destroy
    set res
} {x 1 {} 0}

test fa-state-3.1 {state delete, variadic} {
    grammar::fa a
    a state add x y
    set     res {}
    lappend res [lsort [a states]]
    lappend res [a state exists x]
    lappend res [a state exists y]
    a state delete x y
    lappend res [a states]
    lappend res [a state exists x]
    lappend res [a state exists y]
    a destroy
    set res
} {{x y} 1 1 {} 0 0}

test fa-state-3.2 {state delete, loop} {
    grammar::fa a
    a state  add a
    a symbol add @
    a next a @ --> a
    a state delete a
    a destroy
} {}

test fa-state-3.3 {state delete, inbound transition} {
    grammar::fa a
    gen xyz!-=
    set res [a next x @]
    a state delete y
    lappend res [a next x @]
    a destroy
    set res
} {y {}}


test fa-state-3.4 {state delete, outbound transition} {
    grammar::fa a
    gen xy-
    a state delete x
    a state delete y
    a symbol delete @
    a destroy
    set res {}
} {}


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


test fa-state-4.0 {state, exists} {
    grammar::fa a
    set res [a state exists x]
    a destroy
    set res
} 0


test fa-state-4.1 {state, exists} {
    grammar::fa a
    a state add x
    set res [a state exists x]
    a destroy
    set res
} 1


# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


test fa-state-5.4 {state rename} {
    grammar::fa a
    a state add x y
    a state rename x z
    set res [a serialize]
    a destroy
    set res
} {grammar::fa {} {z {0 0 {}} y {0 0 {}}}}


test fa-state-5.5 {state rename} {
    grammar::fa a
    a state add x y
    a state rename y z
    set res [a serialize]
    a destroy
    set res
} {grammar::fa {} {x {0 0 {}} z {0 0 {}}}}


test fa-state-5.6 {state rename} {
    grammar::fa a
    a state add x y
    a symbol add @
    a next x @ --> y
    a state rename x z
    set res [a serialize]
    a destroy
    set res
} {grammar::fa @ {z {0 0 {@ y}} y {0 0 {}}}}


test fa-state-5.7 {state rename} {
    grammar::fa a
    a state add x y
    a symbol add @
    a next x @ --> y
    a state rename y z
    set res [a serialize]
    a destroy
    set res
} {grammar::fa @ {x {0 0 {@ z}} z {0 0 {}}}}


# -------------------------------------------------------------------------
::tcltest::cleanupTests
