# 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: lcs.test,v 1.5 2004-06-22 17:45:14 peter Exp $

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

package require DiffUtil

# There are differences between the C and the Diff result.
tcltest::testConstraint ExtDiff \
        [expr {[info proc DiffUtil::ExecDiffFiles] != ""}]
tcltest::testConstraint CDiff \
        [expr {[info proc DiffUtil::ExecDiffFiles] == ""}]

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

proc lcs {list1 list2 args} {
    set ch [open _1 w]
    puts -nonewline $ch [join $list1 \n]
    close $ch
    set ch [open _2 w]
    puts -nonewline $ch [join $list2 \n]
    close $ch

    set apa [DiffUtil::diffFiles _1 _2]
    set r1 {}
    set r2 {}
    set prev1 1
    set prev2 1
    foreach chunk $apa {
        foreach {x l1 n1 l2 n2} $chunk break
        puts ""
    }

    return [list $r1 $r2]
}

# Do lcs-tests through diffFiles
proc lcs {list1 list2 args} {
    set ch [open _1 w]
    if {[llength $list1] > 0} {
        puts $ch [join $list1 \n]
    }
    close $ch
    set ch [open _2 w]
    if {[llength $list2] > 0} {
        puts $ch [join $list2 \n]
    }
    close $ch

    #puts "Diff [list $list1 $list2]"
    set apa [DiffUtil::diffFiles _1 _2]
    file delete -force _1 _2
    #puts "L1: [join $list1]"
    #puts "L2: [join $list2]"
    #puts "C : $::DiffUtil::Candidates"
    set r1 {}
    set r2 {}
    set prev1 1
    set prev2 1
    foreach chunk $apa {
        foreach {l1 n1 l2 n2} $chunk break
        # Skip equal lines up to the chunk
        for {} {$prev1 < $l1} {incr prev1 ; incr prev2} {
            lappend r1 [expr {$prev1 - 1}]
            lappend r2 [expr {$prev2 - 1}]
        }
        incr prev1 $n1
        incr prev2 $n2
        #puts "Chunk $chunk"
    }
    set l1 [expr {[llength $list1] + 1}]
    for {} {$prev1 < $l1} {incr prev1 ; incr prev2} {
        lappend r1 [expr {$prev1 - 1}]
        lappend r2 [expr {$prev2 - 1}]
    }
    #puts [list $r1 $r2]
    return [list $r1 $r2]
}

# Do lcs-tests through diffLists
proc lcs {list1 list2 args} {
    set apa [DiffUtil::diffLists $list1 $list2]
    set r1 {}
    set r2 {}
    set prev1 0
    set prev2 0
    foreach chunk $apa {
        foreach {l1 n1 l2 n2} $chunk break
        # Skip equal lines up to the chunk
        for {} {$prev1 < $l1} {incr prev1 ; incr prev2} {
            lappend r1 $prev1
            lappend r2 $prev2
        }
        incr prev1 $n1
        incr prev2 $n2
        #puts "Chunk $chunk"
    }
    set l1 [llength $list1]
    for {} {$prev1 < $l1} {incr prev1 ; incr prev2} {
        lappend r1 $prev1
        lappend r2 $prev2
    }
    #puts [list $r1 $r2]
    return [list $r1 $r2]
}

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} {CDiff} {
    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} {CDiff} {
    list [catch { lcs {a} {b} } msg] $msg
} {0 {{} {}}}

test list-lcs-2.6 {longestCommonSubsequence, insert 1 in front of singleton list} {CDiff} {
    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} {CDiff} {
    list [catch {lcs {a} {a a}} msg] $msg
} {0 {0 0}}

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

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

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

#test list-lcs-2.11.2 {longestCommonSubsequence, insert inside 2} {ExtDiff} {
#    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} {CDiff} {
    list [catch {lcs {a b} a} msg] $msg
} {0 {0 0}}

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

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

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

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

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

test list-lcs-2.19 {longestCommonSubsequence, mixed changes} {CDiff} {
    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} {CDiff} {
    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}}}
