# -*- tcl -*-
# queue.test:  tests for the queue package.
#
# This file contains a collection of tests for one or more of the Tcl
# built-in commands.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 1998-2000 by Ajuba Solutions.
# All rights reserved.
#
# RCS: @(#) $Id: queue.testsuite,v 1.3 2010/05/25 19:26:18 andreas_kupries Exp $

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

::tcltest::testConstraint queue_critcl [string equal $impl critcl]
::tcltest::testConstraint queue_oo     [expr {![catch {package present TclOO}] && [string equal $impl tcl]}]

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

test queue-${impl}-0.1.0 {queue errors} !queue_oo {
    queue myqueue
    catch {queue myqueue} msg
    myqueue destroy
    set msg
} {command "::myqueue" already exists, unable to create queue}

test queue-${impl}-0.1.1 {queue errors} queue_oo {
    queue myqueue
    catch {queue myqueue} msg
    myqueue destroy
    set msg
} {can't create object "myqueue": command already exists with that name}

test queue-${impl}-0.2 {queue errors} badTest {
    queue myqueue
    catch {myqueue} msg
    myqueue destroy
    set msg
} "wrong # args: should be \"$MY option ?arg arg ...?\""

test queue-${impl}-0.3.1.0 {queue errors} !queue_oo {
    queue myqueue
    catch {myqueue foo} msg
    myqueue destroy
    set msg
} [tmTake \
       {unknown or ambiguous subcommand "foo": must be clear, destroy, get, peek, put, size, or unget} \
       {bad option "foo": must be clear, destroy, get, peek, put, size, or unget} \
      ]

test queue-${impl}-0.3.1.1 {queue errors} queue_oo {
    queue myqueue
    catch {myqueue foo} msg
    myqueue destroy
    set msg
} [tmTake \
       {unknown method "foo": must be clear, destroy, get, peek, put, size or unget} \
       {bad option "foo": must be clear, destroy, get, peek, put, size, or unget} \
      ]

test queue-${impl}-0.4.0 {queue errors} !queue_oo {
    catch {queue set} msg
    set msg
} {command "::set" already exists, unable to create queue}

test queue-${impl}-0.4.1 {queue errors} queue_oo {
    catch {queue set} msg
    set msg
} {can't create object "set": command already exists with that name}

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

test queue-${impl}-1.1 {queue creation} {
    set foo [queue myqueue]
    set cmd [info commands ::myqueue]
    set size [myqueue size]
    myqueue destroy
    list $foo $cmd $size
} {::myqueue ::myqueue 0}

test queue-${impl}-1.2.0 {queue creation} !queue_oo {
    set foo [queue]
    set cmd [info commands ::$foo]
    set size [$foo size]
    $foo destroy
    list $foo $cmd $size
} {::queue1 ::queue1 0}

test queue-${impl}-1.2.1 {queue creation} queue_oo {
    set foo [queue]
    set cmd [info commands ::$foo]
    set size [$foo size]
    $foo destroy
    list $foo $cmd $size
    string match [list ::oo::Obj* ::oo::Obj* 0] [list $foo $cmd $size]
} 1

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

test queue-${impl}-2.1 {queue destroy} {
    queue myqueue
    myqueue destroy
    info commands ::myqueue
} {}

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

test queue-${impl}-3.2 {size operation} {
    queue myqueue
    myqueue put a b c d e f g
    set size [myqueue size]
    myqueue destroy
    set size
} 7
test queue-${impl}-3.3 {size operation} {
    queue myqueue
    myqueue put a b c d e f g
    myqueue get 3
    set size [myqueue size]
    myqueue destroy
    set size
} 4
test queue-${impl}-3.4 {size operation} {
    queue myqueue
    myqueue put a b c d e f g
    myqueue get 3
    myqueue peek 3
    set size [myqueue size]
    myqueue destroy
    set size
} 4

#----------------------------------------------------------------------
    
test queue-${impl}-4.1 {put operation} {
    queue myqueue
    catch {myqueue put} msg
    myqueue destroy
    set msg
} "wrong # args: should be \"$MY put item ?item ...?\""

test queue-${impl}-4.2 {put operation, singleton items} {
    queue myqueue
    myqueue put a
    myqueue put b
    myqueue put c
    set result [list [myqueue get] [myqueue get] [myqueue get]]
    myqueue destroy
    set result
} {a b c}

test queue-${impl}-4.3 {put operation, multiple items} {
    queue myqueue
    myqueue put a b c
    set result [list [myqueue get] [myqueue get] [myqueue get]]
    myqueue destroy
    set result
} {a b c}

test queue-${impl}-4.4 {put operation, spaces in items} {
    queue myqueue
    myqueue put a b "foo bar"
    set result [list [myqueue get] [myqueue get] [myqueue get]]
    myqueue destroy
    set result
} {a b {foo bar}}

test queue-${impl}-4.5 {put operation, bad chars in items} {
    queue myqueue
    myqueue put a b \{
    set result [list [myqueue get] [myqueue get] [myqueue get]]
    myqueue destroy
    set result
} [list a b \{]

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

test queue-${impl}-5.1 {get operation} {
    queue myqueue
    myqueue put a
    myqueue put b
    myqueue put c
    set result [list [myqueue get] [myqueue get] [myqueue get]]
    myqueue destroy
    set result
} {a b c}

test queue-${impl}-5.2 {get operation, multiple items} {
    queue myqueue
    myqueue put a
    myqueue put b
    myqueue put c
    set result [myqueue get 3]
    myqueue destroy
    set result
} {a b c}

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

test queue-${impl}-6.1 {peek operation} {
    queue myqueue
    myqueue put a
    myqueue put b
    myqueue put c
    set result [list [myqueue peek] [myqueue peek] [myqueue peek]]
    myqueue destroy
    set result
} {a a a}

test queue-${impl}-6.2 {peek operation} {
    queue myqueue
    catch {myqueue peek 0} msg
    myqueue destroy
    set msg
} {invalid item count 0}

test queue-${impl}-6.3 {peek operation} {
    queue myqueue
    catch {myqueue peek -1} msg
    myqueue destroy
    set msg
} {invalid item count -1}

test queue-${impl}-6.4 {peek operation} {
    queue myqueue
    catch {myqueue peek} msg
    myqueue destroy
    set msg
} {insufficient items in queue to fill request}

test queue-${impl}-6.5 {peek operation} {
    queue myqueue
    myqueue put a
    catch {myqueue peek 2} msg
    myqueue destroy
    set msg
} {insufficient items in queue to fill request}

test queue-${impl}-6.6 {get operation, multiple items} {
    queue myqueue
    myqueue put a
    myqueue put b
    myqueue put c
    set result [list [myqueue peek 3] [myqueue get 3]]
    myqueue destroy
    set result
} {{a b c} {a b c}}

test queue-${impl}-6.7 {get operation} {
    queue myqueue
    catch {myqueue get 0} msg
    myqueue destroy
    set msg
} {invalid item count 0}

test queue-${impl}-6.8 {get operation} {
    queue myqueue
    catch {myqueue get -1} msg
    myqueue destroy
    set msg
} {invalid item count -1}

test queue-${impl}-6.9 {get operation} {
    queue myqueue
    catch {myqueue get} msg
    myqueue destroy
    set msg
} {insufficient items in queue to fill request}

test queue-${impl}-6.10 {get operation} {
    queue myqueue
    myqueue put a
    catch {myqueue get 2} msg
    myqueue destroy
    set msg
} {insufficient items in queue to fill request}

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

test queue-${impl}-7.1 {clear operation} {
    queue myqueue
    myqueue put a
    myqueue put b
    myqueue put c
    set result [list [myqueue peek 3]]
    myqueue clear
    lappend result [myqueue size]
    myqueue destroy
    set result
} {{a b c} 0}

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

test queue-${impl}-8.1 {unget operation, not enough arguments} {
    queue myqueue
    catch {myqueue unget} msg
    myqueue destroy
    set msg
} [tmWrong unget {item} 0]

test queue-${impl}-8.2 {unget operation, too many arguments} {
    queue myqueue
    catch {myqueue unget a b} msg
    myqueue destroy
    set msg
} [tmTooMany unget {item}]

test queue-${impl}-8.3 {unget, empty queue} {
    queue myqueue
    myqueue unget foo
    set res [myqueue peek [myqueue size]]
    myqueue destroy
    set res
} {foo}

test queue-${impl}-8.4 {unget, nonempty queue, at beginning of queue} {
    queue myqueue
    myqueue put a b c
    myqueue unget foo
    set res [myqueue peek [myqueue size]]
    myqueue destroy
    set res
} {foo a b c}

test queue-${impl}-8.5 {unget, nonempty queue, middle of queue} {
    queue myqueue
    myqueue put a b c d e f
    myqueue get 3
    myqueue unget foo
    set res [myqueue peek [myqueue size]]
    myqueue destroy
    set res
} {foo d e f}

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

test queue-${impl}-sf-3608240-a {} {
    struct::queue qp
    qp put 1 2 3
    set r {}
    lappend r [qp peek [qp size]]
    lappend r [qp get]
    lappend r [qp peek [qp size]]
    qp put 4 5
    lappend r [qp peek [qp size]]
    qp destroy
    set r
} {{1 2 3} 1 {2 3} {2 3 4 5}}
catch { unset r }

test queue-${impl}-sf-3608240-b {} {
    struct::queue qp
    qp put 1 2 3
    set r {}
    lappend r [qp peek [qp size]]
    lappend r [qp get]
    lappend r [qp peek [qp size]]
    qp put 4 5
    lappend r [qp get [qp size]]
    qp destroy
    set r
} {{1 2 3} 1 {2 3} {2 3 4 5}}
catch { unset r }

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