# Tests for the 'list' module in the 'struct' library. -*- tcl -*-
#
# This file contains a collection of tests for one or more of the Tcllib
# procedures.  Sourcing this file into Tcl runs the tests and
# generates output for errors.  No output means no errors were found.
#
# Copyright (c) 2003 by Kevin B. Kenny. All rights reserved.
#
# RCS: @(#) $Id: $

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import ::tcltest::*
}

source [file join [file dirname [info script]] list.tcl]

# Fake [lset] for Tcl releases that don't have it.  We need only
# lset into a flat list.

if { [string compare lset [info commands lset]] } {
    proc K { x y } { set x }
    proc lset { listVar index var } {
	upvar 1 $listVar list
	set list [lreplace [K $list [set list {}]] $index $index $var]
    }
}

# Service procedure to develop the error message for "wrong # args"

proc wrongNumArgs {name arglist count} {
    set ver [info patchlevel]
    # strip "a1", etc. designations
    regsub {(a|b)[1-9]$} $ver {} ver
    if {[package vcompare $ver 8.4] < 0} {
	set arg [lindex $arglist $count]
	set msg "no value given for parameter \"$arg\" to \"$name\""
    } else {
	set msg "wrong # args: should be \"$name $arglist\""
    }
    return $msg
}

interp alias {} lcs {} ::struct::list::longestCommonSubsequence

test list-lcs-1.1 {longestCommonSubsequence, no args} {
    catch { lcs } msg
    set msg
} [wrongNumArgs ::struct::list::longestCommonSubsequence \
       {sequence1 sequence2 ?maxOccurs?} 0]

test list-lcs-1.2 {longestCommonSubsequence, one arg} {
    catch { lcs x } msg
    set msg
} [wrongNumArgs ::struct::list::longestCommonSubsequence \
       {sequence1 sequence2 ?maxOccurs?} 1]

test list-lcs-2.1 {longestCommonSubsequence, two empty lists} {
    list [catch { lcs {} {} } msg] $msg
} {0 {{} {}}}

test list-lcs-2.2 {longestCommonSubsequence, insert 1 into an empty list} {
    list [catch { lcs {} {a} } msg] $msg
} {0 {{} {}}}

test list-lcs-2.3 {longestCommonSubsequence, delete 1 from singleton list} {
    list [catch { lcs {a} {} } msg] $msg
} {0 {{} {}}}

test list-lcs-2.4 {longestCommonSubsequence, preserve singleton list} {
    list [catch { lcs {a} {a} } msg] $msg
} {0 {0 0}}

test list-lcs-2.5 {longestCommonSubsequence, 1-element change in singleton list} {
    list [catch { lcs {a} {b} } msg] $msg
} {0 {{} {}}}

test list-lcs-2.6 {longestCommonSubsequence, insert 1 in front of singleton list} {
    list [catch { lcs {a} {b a} } msg] $msg
} {0 {0 1}}

test list-lcs-2.7 {longestCommonSubsequence, insert 1 at end of singleton list} {
    list [catch {lcs {a} {a b}} msg] $msg
} {0 {0 0}}

test list-lcs-2.8 {longestCommonSubsequence, duplicate element} {
    list [catch {lcs {a} {a a}} msg] $msg
} {0 {0 0}}

test list-lcs-2.9 {longestCommonSubsequence, interchange 2} {
    list [catch {lcs {a b} {b a}} msg] $msg
} {0 {1 0}}

test list-lcs-2.10 {longestCommonSubsequence, insert before 2} {
    list [catch {lcs {a b} {b a b}} msg] $msg
} {0 {{0 1} {1 2}}}

test list-lcs-2.11 {longestCommonSubsequence, insert inside 2} {
    list [catch {lcs {a b} {a a b}} msg] $msg
} {0 {{0 1} {0 2}}}

test list-lcs-2.13 {longestCommonSubsequence, insert after 2} {
    list [catch {lcs {a b} {a b a}} msg] $msg
} {0 {{0 1} {0 1}}}

test list-lcs-2.13 {longestCommonSubsequence, delete first of 2} {
    list [catch {lcs {a b} a} msg] $msg
} {0 {0 0}}

test list-lcs-2.14 {longestCommonSubsequence, delete second of 2} {
    list [catch {lcs {a b} b} msg] $msg
} {0 {1 0}}

test list-lcs-2.15 {longestCommonSubsequence, change first of 2} {
    list [catch {lcs {a b} {c b}} msg] $msg
} {0 {1 1}}

test list-lcs-2.16 {longestCommonSubsequence, change first of 2 to dupe} {
    list [catch {lcs {a b} {b b}} msg] $msg
} {0 {1 0}}

test list-lcs-2.17 {longestCommonSubsequence, change second of 2} {
    list [catch {lcs {a b} {a c}} msg] $msg
} {0 {0 0}}

test list-lcs-2.18 {longestCommonSubsequence, change second of 2 to dupe} {
    list [catch {lcs {a b} {a a}} msg] $msg
} {0 {0 0}}

test list-lcs-2.19 {longestCommonSubsequence, mixed changes} {
    list [catch {lcs {a b r a c a d a b r a} {b r i c a b r a c}} msg] $msg
} {0 {{1 2 4 5 8 9 10} {0 1 3 4 5 6 7}}}

test list-lcs-2.20 {longestCommonSubsequence, mixed changes} {
    list [catch {lcs {b r i c a b r a c} {a b r a c a d a b r a}} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}

test list-lcs-3.1 {longestCommonSubsequence, length limit} {
    list [catch {lcs {b r i c a b r a c} {a b r a c a d a b r a} 5} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}

test list-lcs-3.2 {longestCommonSubsequence, length limit} {
    list [catch {lcs {b r i c a b r a c} {a b r a c a d a b r a} 4} msg] $msg
} {0 {{0 1 3 5 6} {1 2 4 8 9}}}

test list-lcs-3.3 {longestCommonSubsequence, length limit} {
    list [catch {lcs {b r i c a b r a c} {a b r a c a d a b r a} 1} msg] $msg
} {0 {3 4}}

test list-lcs-3.4 {longestCommonSubsequence, stupid length limit} {
    list [catch {lcs {b r i c a b r a c} {a b r a c a d a b r a} 0} msg] $msg
} {0 {{} {}}}

interp alias {} lcs2 {} ::struct::list::longestCommonSubsequence2

test list-lcs2-1.1 {longestCommonSubsequence2, no args} {
    catch { lcs2 } msg
    set msg
} [wrongNumArgs ::struct::list::longestCommonSubsequence2 \
       {sequence1 sequence2 ?maxOccurs?} 0]

test list-lcs2-1.2 {longestCommonSubsequence2, one arg} {
    catch { lcs2 x } msg
    set msg
} [wrongNumArgs ::struct::list::longestCommonSubsequence2 \
       {sequence1 sequence2 ?maxOccurs?} 1]

test list-lcs2-2.1 {longestCommonSubsequence2, two empty lists} {
    list [catch { lcs2 {} {} } msg] $msg
} {0 {{} {}}}

test list-lcs2-2.2 {longestCommonSubsequence2, insert 1 into an empty list} {
    list [catch { lcs2 {} {a} } msg] $msg
} {0 {{} {}}}

test list-lcs2-2.3 {longestCommonSubsequence2, delete 1 from singleton list} {
    list [catch { lcs2 {a} {} } msg] $msg
} {0 {{} {}}}

test list-lcs2-2.4 {longestCommonSubsequence2, preserve singleton list} {
    list [catch { lcs2 {a} {a} } msg] $msg
} {0 {0 0}}

test list-lcs2-2.5 {longestCommonSubsequence2, 1-element change in singleton list} {
    list [catch { lcs2 {a} {b} } msg] $msg
} {0 {{} {}}}

test list-lcs2-2.6 {longestCommonSubsequence2, insert 1 in front of singleton list} {
    list [catch { lcs2 {a} {b a} } msg] $msg
} {0 {0 1}}

test list-lcs2-2.7 {longestCommonSubsequence2, insert 1 at end of singleton list} {
    list [catch {lcs2 {a} {a b}} msg] $msg
} {0 {0 0}}

test list-lcs2-2.8 {longestCommonSubsequence2, duplicate element} {
    list [catch {lcs2 {a} {a a}} msg] $msg
} {0 {0 0}}

test list-lcs2-2.9 {longestCommonSubsequence2, interchange 2} {
    list [catch {lcs2 {a b} {b a}} msg] $msg
} {0 {1 0}}

test list-lcs2-2.10 {longestCommonSubsequence2, insert before 2} {
    list [catch {lcs2 {a b} {b a b}} msg] $msg
} {0 {{0 1} {1 2}}}

test list-lcs2-2.11 {longestCommonSubsequence2, insert inside 2} {
    list [catch {lcs2 {a b} {a a b}} msg] $msg
} {0 {{0 1} {0 2}}}

test list-lcs2-2.13 {longestCommonSubsequence2, insert after 2} {
    list [catch {lcs2 {a b} {a b a}} msg] $msg
} {0 {{0 1} {0 1}}}

test list-lcs2-2.13 {longestCommonSubsequence2, delete first of 2} {
    list [catch {lcs2 {a b} a} msg] $msg
} {0 {0 0}}

test list-lcs2-2.14 {longestCommonSubsequence2, delete second of 2} {
    list [catch {lcs2 {a b} b} msg] $msg
} {0 {1 0}}

test list-lcs2-2.15 {longestCommonSubsequence2, change first of 2} {
    list [catch {lcs2 {a b} {c b}} msg] $msg
} {0 {1 1}}

test list-lcs2-2.16 {longestCommonSubsequence2, change first of 2 to dupe} {
    list [catch {lcs2 {a b} {b b}} msg] $msg
} {0 {1 0}}

test list-lcs2-2.17 {longestCommonSubsequence2, change second of 2} {
    list [catch {lcs2 {a b} {a c}} msg] $msg
} {0 {0 0}}

test list-lcs2-2.18 {longestCommonSubsequence2, change second of 2 to dupe} {
    list [catch {lcs2 {a b} {a a}} msg] $msg
} {0 {0 0}}

test list-lcs2-2.19 {longestCommonSubsequence2, mixed changes} {
    list [catch {lcs2 {a b r a c a d a b r a} {b r i c a b r a c}} msg] $msg
} {0 {{1 2 4 5 8 9 10} {0 1 3 4 5 6 7}}}

test list-lcs2-2.20 {longestCommonSubsequence2, mixed changes} {
    list [catch {lcs2 {b r i c a b r a c} {a b r a c a d a b r a}} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}

test list-lcs2-3.1 {longestCommonSubsequence2, length limit} {
    list [catch {lcs2 {b r i c a b r a c} {a b r a c a d a b r a} 5} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}

test list-lcs2-3.2 {longestCommonSubsequence2, length limit} {
    list [catch {lcs2 {b r i c a b r a c} {a b r a c a d a b r a} 4} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}

test list-lcs2-3.3 {longestCommonSubsequence2, length limit} {
    list [catch {lcs2 {b r i c a b r a c} {a b r a c a d a b r a} 1} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}

test list-lcs2-3.4 {longestCommonSubsequence2, stupid length limit} {
    list [catch {lcs2 {b r i c a b r a c} {a b r a c a d a b r a} 0} msg] $msg
} {0 {{0 1 3 4 5 6 7} {1 2 4 5 8 9 10}}}
