# Tests for the 'DiffUtil' package. -*- tcl -*-
#
# Copyright (c) 2004 by Peter Spjuth. All rights reserved.
#
# $Revision: 1.8 $

package require DiffUtil

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

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

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

# A wrapper to simplify calling
proc RunTest {list1 list2 args} {
    set apa [catch {eval DiffUtil::diffLists $args \$list1 \$list2} res]
    return $res
}

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

test difflists-1.1 {standard cases} {CDiff} {
    set l1 {a b c d   f g h i j k l}
    set l2 {  b c d e f g x y   k l}
    RunTest $l1 $l2
} [list {0 1 0 0} {4 0 3 1} {6 3 6 2}]

test difflists-1.2 {standard cases, error} -constraints {CDiff} -body {
    set l1 {a b c d   f g h i j k l}
    set l2 {  b c d e f g x y   k l}
    RunTest $l1 $l2 -hubba
} -result {bad option "-hubba"*} -match glob

test difflists-1.3 {standard cases, error} -constraints {CDiff} -body {
    DiffUtil::diffLists a
} -returnCodes 1 -result "wrong # args*" -match glob

test difflists-3.1 {ignore space} {CDiff} {
    set l1 {a {b c} d e f {g h}  i}
    set l2 {a {bc}  x e f {g  h} i}
    RunTest $l1 $l2
} [list {1 2 1 2} {5 1 5 1}]

test difflists-3.2 {ignore space} {CDiff} {
    set l1 {a {b c} d e f {g h}  i}
    set l2 {a {bc}  x e f {g  h} i}
    RunTest $l1 $l2 -b
} [list {1 2 1 2}]

test difflists-3.3 {ignore space} {CDiff} {
    set l1 {a {b c} d e f {g h}  i}
    set l2 {a {bc}  x e f {g  h} i}
    RunTest $l1 $l2 -w
} [list {2 1 2 1}]

test difflists-4.1 {trivial cases} {CDiff} {
    set l1 {}
    set l2 {a b c}
    RunTest $l1 $l2
} [list {0 0 0 3}]

test difflists-4.1b {trivial cases} {CDiff} {
    set l1 {}
    set l2 {a b c}
    RunTest $l1 $l2 -result match
} [list {} {}]

test difflists-4.2 {trivial cases} {CDiff} {
    set l1 {a b}
    set l2 {}
    RunTest $l1 $l2
} [list {0 2 0 0}]

test difflists-4.2b {trivial cases} {CDiff} {
    set l1 {a b}
    set l2 {}
    RunTest $l1 $l2 -result match
} [list {} {}]

test difflists-4.3 {trivial cases} {CDiff} {
    set l1 {}
    set l2 {}
    RunTest $l1 $l2
} [list ]

test difflists-4.3b {trivial cases} {CDiff} {
    set l1 {}
    set l2 {}
    RunTest $l1 $l2 -result match
} [list {} {}]

test difflists-5.1 {priority} {CDiff} {
    # The changed block is kept together
    set l1 {a b c d       e}
    set l2 {a b c d f e E e}
    RunTest $l1 $l2
} [list {4 0 4 3}]

test difflists-5.2 {priority} {CDiff} {
    # No prio here, just a reference for the following nocase
    set l1 {a b c d   e}
    set l2 {a b c d f e E}
    RunTest $l1 $l2
} [list {4 0 4 1} {5 0 6 1}]

test difflists-5.3 {priority} {CDiff} {
    # Same case as before but with prio
    # The correct case has priority even if it means two changes
    set l1 {a b c d   e}
    set l2 {a b c d f e E}
    RunTest $l1 $l2 -nocase
} [list {4 0 4 1} {5 0 6 1}]

test difflists-5.4 {priority} {CDiff} {
    # Same case again but no correct case, single block preferred
    set l1 {a b c d     e}
    set l2 {a b c d f E E}
    RunTest $l1 $l2 -nocase
} [list {4 0 4 2}]

test difflists-5.5 {priority} {CDiff} {
    # Here efgh can match in two places, the first is chosen
    set l1 {a b c d   e f g h             i j k l}
    set l2 {a b c d X e f g h Y e f g h Z i j k l}
    RunTest $l1 $l2
} [list {4 0 4 1} {8 0 9 6}]

test difflists-5.6 {priority} {CDiff} {
    # Here efgh can match in two places, the second is chosen since it
    # keeps things together
    set l1 {a b c d             e f g h i j k l}
    set l2 {a b c d X e f g h Y e f g h i j k l}
    RunTest $l1 $l2
} [list {4 0 4 6}]

test difflists-5.7 {priority} {CDiff} {
    # Multiple blocks starting alike where one block is removed
    set l1 {a b c d e {} a b f g h {} a b i j k}
    set l2 {a b c d e {}              a b i j k}
    # 6    {a b c d e              {} a b i j k}
    # 7    {a b c d e {}              a b i j k}
    # 8    {a b c d e {} a              b i j k}
    # 9    {a b c d e {} a b              i j k}
    list [RunTest $l1 $l2] [RunTest $l2 $l1]
    # Any start line from 6-9 are correct bet from a visual point of
    # view 6 or 7 are preferable.
} [list [list {6 6 6 0}] [list {6 0 6 6}]]

#test difflists-5.7.2 {priority} {TclDiff} { # Same as 5.7, tcl version
#    set l1 {a b c d e {} a b f g h {} a b i j k}
#    set l2 {a b c d e {}              a b i j k}
#    RunTest $l1 $l2
#} [list {9 6 9 0}]

test difflists-5.8 {priority} {CDiff} {
    # Multiple blocks ending alike where one block is removed
    set l1 {a b c d e {} f g h d e {} i j k d e}
    set l2 {a b c d e {}              i j k d e}
    RunTest $l1 $l2
    # Any start line from 6-9 are correct bet from a visual point of
    # view 6 or 7 are preferable.
} [list {6 6 6 0}]

test difflists-6.1 {noempty} {CDiff} {
    set l1 {a b c {} d {}   e f g}
    set l2 {a b c {}   {} d e f g}
    RunTest $l1 $l2
} [list {4 1 4 0} {6 0 5 1}]

test difflists-6.2 {noempty} {CDiff} {
    set l1 {a b c {}    d {} e f g}
    set l2 {a b c {} {} d    e f g}
    RunTest $l1 $l2 -noempty
} [list {4 0 4 1} {5 1 6 0}]

test difflists-6.3 {noempty} {CDiff} {
    set l1 {a b c {} {}    d {} e f g}
    set l2 {a b c {} {} {} d    e f g}
    RunTest $l1 $l2 -noempty
} [list {5 0 5 1} {6 1 7 0}]

test difflists-7.1 {ignore digit} {CDiff} {
    set l1 {a b123c x b02c   b13c d}
    set l2 {a         b02c x      d}
    list [RunTest $l1 $l2] [RunTest $l1 $l2 -nodigit]
} [list [list {1 2 1 0} {4 1 2 1}] [list {3 2 3 0}]]

test difflists-7.2 {ignore digit} {
    set l1 {a b123 12c 456   a76b93u x}
    set l2 {a b2   1c  7890  a0b12u  x}
    RunTest $l1 $l2 -nodigit
} {}

test difflists-7.3.1 {ignore digit, preference} {CDiff} {
    set l1 {a b123 b456 x}
    set l2 {a b123      x}
    set l3 {a b222      x}
    set l4 {a b456      x}
    list [RunTest $l1 $l2 -nodigit] \
            [RunTest $l1 $l3 -nodigit] \
            [RunTest $l1 $l4 -nodigit]
} [list [list {2 1 2 0}] [list {2 1 2 0}] [list {1 1 1 0}]]

#test difflists-7.3.2 {ignore digit, preference} {TclDiff} {
#    set l1 {a b123 b456 x}
#    set l2 {a b123      x}
#    set l3 {a b222      x}
#    set l4 {a b456      x}
#    list [RunTest $l1 $l2 -nodigit] \
#            [RunTest $l1 $l3 -nodigit] \
#            [RunTest $l1 $l4 -nodigit]
#} [list [list {3 1 3 0}] [list {3 1 3 0}] [list {3 1 3 0}]]

#test difflists-8.1 {flag -regsub} {CDiff} {
#    set l1 {axa byb aa bb}
#    set l2 {aya bxb ee ff}
#    list [RunTest $l1 $l2] [RunTest $l1 $l2 -regsub {{x|y} {}}]
#} [list [list {1 4 1 4}] [list {3 2 3 2}]]

#test difflists-8.2 {flag -regsub} {CDiff} {
#    set l1 {axa byb axa bb}
#    set l2 {    aya bxb ee ff}
#    list [RunTest $l1 $l2] [RunTest $l1 $l2 -regsub {{.*(y|x).*} {\1}}]
#} [list [list {1 4 1 4}] [list {1 1 1 0} {4 1 3 2}]]

test difflists-9.1 {hash} {CDiff} {
    # Different elements that hash to the same thing.
    # Hash is currenctly hash = hash*129+char, and run over utf-8 string.
    # \x83 becomes \xc2 \x83 in utf-8.
    set l1 {a ab\x83 c}
    set l2 {a ac\x42\x02 c}
    RunTest $l1 $l2
} [list {1 1 1 1}]

test difflists-10.1 {result style} -constraints {CDiff} -body {
    DiffUtil::diffLists -result {} {}
} -returnCodes 1 -result "wrong # args*" -match glob

test difflists-10.2 {result style} -constraints {CDiff} -body {
    DiffUtil::diffLists -result gurka {} {}
} -returnCodes 1 -result {bad result style "gurka": must be diff or match}

test difflists-10.3 {result style} {CDiff} {
    set l1 {a b c}
    set l2 {a d c}
    RunTest $l1 $l2 -result diff
} [list {1 1 1 1}]

test difflists-10.4 {result style} {CDiff} {
    set l1 {a b c}
    set l2 {a d c}
    RunTest $l1 $l2 -result match
} [list {0 2} {0 2}]

test difflists-10.5 {result style} {CDiff} {
    set l1 {a b c d   f g h i j k l}
    set l2 {  b c d e f g x y   k l}
    RunTest $l1 $l2 -result match
} [list {1 2 3 4 5 9 10} {0 1 2 4 5 8 9}]
