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

package require DiffUtil

if {[lsearch [namespace children] ::tcltest] == -1} {
    package require tcltest
    namespace import ::tcltest::*
}
#tcltest::configure -match diffstrings-5.*

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

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

# A wrapper to simplify calling
proc RunTest {str1 str2 args} {
    # FIXA: run with str1/str2 switched, compare
    set c [catch {eval DiffUtil::diffStrings $args \$str1 \$str2} apa]
    set c [catch {eval DiffUtil::diffStrings2 $args \$str1 \$str2} bepa]
    if {$apa ne $bepa} {
        return $apa\n$bepa
    }
    return $apa
}
# Run just one version
proc RunTest1 {str1 str2 args} {
    set c [catch {eval DiffUtil::diffStrings $args \$str1 \$str2} apa]
    return $apa
}
# Run just one version
proc RunTest2 {str1 str2 args} {
    set c [catch {eval DiffUtil::diffStrings2 $args \$str1 \$str2} apa]
    return $apa
}
# Remove spaces before calling, to allow visual formatting in test cases
proc RunTestNoSp {str1 str2 args} {
    set s1 [string map {{ } {}} $str1]
    set s2 [string map {{ } {}} $str2]
    return [RunTest $s1 $s2 {*}$args]
}
proc RunTestNoSp1 {str1 str2 args} {
    set s1 [string map {{ } {}} $str1]
    set s2 [string map {{ } {}} $str2]
    return [RunTest1 $s1 $s2 {*}$args]
}
proc RunTestNoSp2 {str1 str2 args} {
    set s1 [string map {{ } {}} $str1]
    set s2 [string map {{ } {}} $str2]
    return [RunTest2 $s1 $s2 {*}$args]
}

if {[info commands DiffUtil::diffStrings2] == ""} {
    interp alias {} DiffUtil::diffStrings2 {} DiffUtil::diffStrings
}

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

test diffstrings-1.0a {error cases} -body {
    DiffUtil::diffStrings a
} -returnCodes 1 -result "wrong # args*" -match glob

test diffstrings-1.0b {error cases} -body {
    DiffUtil::diffStrings2 a
} -returnCodes 1 -result "wrong # args*" -match glob

test diffstrings-1.1 {substring} {
    set s1 {abcdefghijkl}
    set s2    {def}
    RunTest $s1 $s2
} [list {} {} abc {} def def ghijkl {} {} {}]

test diffstrings-1.2 {substring} {
    set s1     {efghij}
    set s2 {abcdefghijkl}
    RunTest $s1 $s2
} [list {} {} {} abcd efghij efghij {} kl {} {}]

test diffstrings-1.3 {x} {
    set s1 {sks   fliuslkjuf   hslk  flkj}
    set s2 {sksjdhfliu   jufliuhslkxhflkj}
    RunTestNoSp $s1 $s2
} [list sks sks {} jdh fliu fliu slk {} juf juf {} liu hslk hslk {} xh flkj flkj]

test diffstrings-1.4 {equal} {
    set s1 {abc def}
    set s2 {abc def}
    RunTest $s1 $s2
} [list {abc def} {abc def}]

test diffstrings-1.5a {long substring that is not a solution} {
    # Known bug: no good in 1-version
    set s1 {s abcefgijkmno peter                 j}
    set s2 {s              peter abcdefghijklmno j}
    RunTestNoSp1 $s1 $s2
} [list s s abcefgijkmno {} peter peter {} abcdefghijklmno j j]

test diffstrings-1.5b {long substring that is not a solution} {CDiff} {
    set s1 {s     abc efg ijk mnopeterj}
    set s2 {speterabcdefghijklmno     j}
    RunTestNoSp2 $s1 $s2
} [list s s {} peter abc abc {} d efg efg {} h ijk ijk {} l mno mno peter {} j j]

test diffstrings-1.6 {middle addition} {
    set s1 {abc def}
    set s2 {abc xyz def}
    RunTest $s1 $s2
} [list {abc } {abc } {} {xyz } {def} {def}]

test diffstrings-1.7 {middle change} {
    set s1 {abc qqqqqqqq def}
    set s2 {abc wwwwwwww def}
    RunTest $s1 $s2
} [list {abc } {abc } {qqqqqqqq} {wwwwwwww} { def} { def}]

test diffstrings-2.1 {words} {
    set s1 {abc def ghi}
    set s2 {abc daf ghi}
    RunTest $s1 $s2
} [list {abc d} {abc d} e a {f ghi} {f ghi}]

test diffstrings-2.2 {words} {
    set s1 {abc def ghi}
    set s2 {abc daf ghi}
    RunTest $s1 $s2 -words
} [list {abc } {abc } {def} {daf} { ghi} { ghi}]

test diffstrings-2.3 {words} {
    set s1 {abc def ghi jkl mno}
    set s2 {abc daf ghi jil mno}
    RunTest $s1 $s2 -words
} [list {abc } {abc } def daf { ghi } { ghi } jkl jil { mno} { mno}]

test diffstrings-2.4.1a {words} {CDiff} {
    # Known bug: words is not so good in 1-version
    set s1 {abc def ghi}
    set s2 {abc de}
    RunTest1 $s1 $s2 -words
} [list {abc de} {abc de} {f ghi} {} {} {}]

test diffstrings-2.4.1b {words} {CDiff} {
    set s1 {abc def ghi}
    set s2 {abc de}
    RunTest2 $s1 $s2 -words
} [list {abc } {abc } {def ghi} {de} {} {}]

test diffstrings-2.4.2 {words} {TclDiff} {
    set s1 {abc def ghi}
    set s2 {abc de}
    RunTest $s1 $s2 -words
} [list {abc de} {abc de} {f ghi} {} {} {}]

test diffstrings-2.5 {words} {
    # non-space is considered word char
    set s1 {NET '/I$1/N$1458' IC2-10}
    set s2 {NET '/I$1/N$1458' IC2-9}
    RunTest $s1 $s2 -words
} [list {NET '/I$1/N$1458' } {NET '/I$1/N$1458' } IC2-10 IC2-9 {} {}]

test diffstrings-2.6.1 {words} {
    set s1 {apa bepa cepa depa hurg}
    set s2 {apa bipa cepa dipa hurg}
    RunTest $s1 $s2
} [list {apa b} {apa b} e i {pa cepa d} {pa cepa d} e i {pa hurg} {pa hurg}]

test diffstrings-2.6.2 {words} {
    set s1 {apa bepa cepa depa hurg}
    set s2 {apa bipa cepa dipa hurg}
    RunTest $s1 $s2 -words
} [list {apa } {apa } bepa bipa { cepa } { cepa } depa dipa { hurg} { hurg}]

test diffstrings-2.7.2a {words} {
    # Known: 1 do not handle this well
    set s1 { apa  bepa   cepa  depa   hurg}
    set s2 { apa   bipa  cepa  dipa   hurg }
    RunTest1 $s1 $s2 -words -b
} [list { apa  } { apa  } {bepa } { bipa} {  cepa  } {  cepa  } depa dipa {   hurg} {   hurg }]

test diffstrings-2.7.2b {words} {CDiff} {
    set s1 { apa  bepa   cepa  depa   hurg}
    set s2 { apa   bipa  cepa  dipa   hurg }
    RunTest2 $s1 $s2 -words -b
} [list { apa  } { apa   } bepa bipa {   cepa  } {  cepa  } depa dipa {   hurg} {   hurg} {} { } {} {}]

test diffstrings-2.7.3a {words} {
    # Known: 1 do not handle this well
    set s1 { apa  bepa   cepa  depa   hurg}
    set s2 { apa   bipa  cepa  dipa   hurg }
    RunTest1 $s1 $s2 -words -w
} [list { apa  } { apa  } {bepa } { bipa} {  cepa  } {  cepa  } depa dipa {   hurg} {   hurg }]

test diffstrings-2.7.3b {words} {CDiff} {
    # Known: words + -w behaves like -b
    set s1 { apa  bepa   cepa  depa   hurg}
    set s2 { apa   bipa  cepa  dipa   hurg }
    RunTest2 $s1 $s2 -words -w
} [list { apa  } { apa   } bepa bipa {   cepa  } {  cepa  } depa dipa {   hurg} {   hurg} {} { } {} {}]


test diffstrings-3.1a {ignore space} {} {
    # First try without
    set s1 {  abc d  f ghi }
    set s2 { abc x y ghi  }
    RunTest1 $s1 $s2
} [list { } { } { } {} {abc } {abc } {d  f} {x y} { ghi} { ghi} {} { } { } { }]

test diffstrings-3.1b {ignore space} {CDiff} {
    # Known difference: More granularity in 2-version
    set s1 {  abc d  f ghi }
    set s2 { abc x y ghi  }
    RunTest2 $s1 $s2
} [list { } { } { } {} {abc } {abc } d x { } { } { f} y { ghi } { ghi } {} { } {} {}]

test diffstrings-3.2a {ignore space} {
    # Same as 3.1 but with ignore
    set s1 {  abc d  f ghi }
    set s2 { abc x y ghi  }
    RunTest1 $s1 $s2 -b
} [list {  abc } { abc } {d  f} {x y} { ghi } { ghi  }]

test diffstrings-3.2b {ignore space} {CDiff} {
    # Known difference: More granularity in 2-version
    set s1 {  abc d  f ghi }
    set s2 { abc x y ghi  }
    RunTest2 $s1 $s2 -b
} [list {  abc } { abc } d x {  } { } f y { ghi } { ghi  }]

test diffstrings-3.3a {ignore space} {
    # Space change at end of line
    set s1 {  abdef}
    set s2 {  abdef  }
    RunTest1 $s1 $s2 -b
} [list {  abdef} {  abdef  }]

test diffstrings-3.3b {ignore space} {
    # Space change at end of line
    set s1 {  abdef}
    set s2 {  abdef  }
    RunTest2 $s1 $s2 -b
    # Not sure this is correct. TODO
} [list {  abdef} {  abdef} {} {  } {} {}]

test diffstrings-3.4 {ignore space} {
    # Space change at beginning of line
    set s1 {  abdef}
    set s2 {   abdef}
    RunTest $s1 $s2 -b
} [list {  abdef} {   abdef}]

test diffstrings-3.5 {ignore space} {
    # Space change at both ends
    set s1 {  abdef  }
    set s2 {   abcef   }
    RunTest $s1 $s2 -b
} [list {  ab} {   ab} d c {ef  } {ef   }]

test diffstrings-4.1 {ignore case} {
    set s1 {Zabc dWRTUf ghiQ}
    set s2 {zabc xwrtuy ghiq}
    RunTest $s1 $s2
} [list {} {} {Z} {z} {abc } {abc } {dWRTUf} {xwrtuy} { ghi} { ghi} {Q} {q} {} {}]

test diffstrings-4.2 {ignore case} {
    set s1 {Zabc dWRTUf ghiQ}
    set s2 {zabc xwrtuy ghiq}
    RunTest $s1 $s2 -nocase
} [list {Zabc } {zabc } {d} {x} {WRTU} {wrtu} {f} {y} { ghiQ} { ghiq}]

test diffstrings-4.3 {ignore case} {
    set s1 {AjkHFAkjaaslkJADADlkhaDkhALDKJHDA}
    set s2 {AjkhfAkqqAslkJAdaDlsxaDkhAftKJHDA}
    RunTest $s1 $s2 -nocase
} [list {AjkHFAk} {AjkhfAk} {ja} {qq} {aslkJADADl} {AslkJAdaDl} {kh} {sx} {aDkhA} {aDkhA} {LD} {ft} {KJHDA} {KJHDA}]

test diffstrings-5.1 {performance} {
    set s1 {AjkHFAk jaaslkJADADl khaDkhA LDKJHDA}
    set s2 {AjkhfAk qqAslkJAdaDls xaDkh AftKJHDA}

    set n 1000
    puts [time {DiffUtil::diffStrings $s1 $s2} $n]
    puts [time {DiffUtil::diffStrings2 $s1 $s2} $n]
    puts [time {DiffUtil::diffStrings -nocase $s1 $s2} $n]
    puts [time {DiffUtil::diffStrings2 -nocase $s1 $s2} $n]
    puts [time {DiffUtil::diffStrings -b $s1 $s2} $n]
    puts [time {DiffUtil::diffStrings2 -b $s1 $s2} $n]
    set a ""
} {}
