summaryrefslogtreecommitdiffstats
path: root/tests/listRep.test
diff options
context:
space:
mode:
Diffstat (limited to 'tests/listRep.test')
-rw-r--r--tests/listRep.test2538
1 files changed, 2538 insertions, 0 deletions
diff --git a/tests/listRep.test b/tests/listRep.test
new file mode 100644
index 0000000..7883a21
--- /dev/null
+++ b/tests/listRep.test
@@ -0,0 +1,2538 @@
+# This file contains tests that specifically exercise the internal representation
+# of a list.
+#
+# Copyright © 2022 Ashok P. Nadkarni
+#
+# See the file "license.terms" for information on usage and redistribution
+# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+
+# Unlike the other files related to list commands which for the most part do
+# black box testing focusing on functionality, this file does more of white box
+# testing to exercise code paths that implement different list representations
+# (with spans, leading free space etc., shared/unshared etc.) In addition to
+# functional correctness, the tests also check for the expected internal
+# representation as that pertains to performance heuristics. Generally speaking,
+# combinations of the following need to be tested,
+# - free space in front, back, neither, both of list representation
+# - shared Tcl_Objs
+# - shared internal reps (independent of shared Tcl_Objs)
+# - byte-compiled vs non-compiled
+#
+# Being white box tests, they are sensitive to changes to further optimizations
+# and changes in heuristics. That cannot be helped.
+
+if {"::tcltest" ni [namespace children]} {
+ package require tcltest 2.5
+ namespace import -force ::tcltest::*
+}
+
+::tcltest::loadTestedCommands
+catch [list package require -exact tcl::test [info patchlevel]]
+
+testConstraint testlistrep [llength [info commands testlistrep]]
+
+proc describe {l args} {dict get [testlistrep describe $l] {*}$args}
+
+proc irange {first last} {
+ set l {}
+ while {$first <= $last} {
+ lappend l $first
+ incr first
+ }
+ return $l
+}
+proc leadSpace {l} {
+ # Returns the leading space in a list store
+ return [dict get [describe $l] store firstUsed]
+}
+proc tailSpace {l} {
+ # Returns the trailing space in a list store
+ array set rep [describe $l]
+ dict with rep(store) {
+ return [expr {$numAllocated - ($firstUsed + $numUsed)}]
+ }
+}
+proc allocated {l} {
+ # Returns the allocated space in a list store
+ return [dict get [describe $l] store numAllocated]
+}
+proc repStoreRefCount {l} {
+ # Returns the ref count for the list store
+ return [dict get [describe $l] store refCount]
+}
+proc validate {l} {
+ # Panics if internal listrep structures are not valid
+ testlistrep validate $l
+}
+proc leadSpaceMore {l} {
+ set leadSpace [leadSpace $l]
+ expr {$leadSpace > 0 && $leadSpace >= 2*[tailSpace $l]}
+}
+proc tailSpaceMore {l} {
+ set tailSpace [tailSpace $l]
+ expr {$tailSpace > 0 && $tailSpace >= 2*[leadSpace $l]}
+}
+proc spaceEqual {l} {
+ # 1 if lead and tail space shared (diff of 1 at most) and more than 0
+ set leadSpace [leadSpace $l]
+ set tailSpace [tailSpace $l]
+ if {$leadSpace == 0 && $tailSpace == 0} {
+ # At least one must be positive
+ return 0
+ }
+ set diff [expr {$leadSpace - $tailSpace}]
+ return [expr {$diff >= -1 && $diff <= 1}]
+}
+proc storeAddress {l} {
+ return [describe $l store memoryAddress]
+}
+proc sameStore {l1 l2} {
+ expr {[storeAddress $l1] == [storeAddress $l2]}
+}
+proc hasSpan {l args} {
+ # Returns 1 if list has a span. If args are specified, they are checked with
+ # span values (start and length)
+ array set rep [describe $l]
+ if {![info exists rep(span)]} {
+ return 0
+ }
+ if {[llength $args] == 0} {
+ return 1; # No need to check values
+ }
+ lassign $args start len
+ if {[dict get $rep(span) spanStart] == $start &&
+ [dict get $rep(span) spanLength] == $len} {
+ return 1
+ }
+ return 0
+}
+proc checkListrep {l listLen numAllocated leadSpace tailSpace {refCount 0}} {
+ # Checks if the internal representation of $l match
+ # passed arguments. Return "" if yes, else error messages.
+ array set rep [testlistrep describe $l]
+
+ set rep(leadSpace) [dict get $rep(store) firstUsed]
+ set rep(numAllocated) [dict get $rep(store) numAllocated]
+ set rep(tailSpace) [expr {
+ $rep(numAllocated) - ($rep(leadSpace) + [dict get $rep(store) numUsed])
+ }]
+ set rep(refCount) [dict get $rep(store) refCount]
+
+ if {[info exists rep(span)]} {
+ set rep(listLen) [dict get $rep(span) spanLength]
+ } else {
+ set rep(listLen) [dict get $rep(store) numUsed]
+ }
+
+ set errors [list]
+ foreach arg {listLen numAllocated leadSpace tailSpace} {
+ if {$rep($arg) != [set $arg]} {
+ lappend errors "$arg in list representation ($rep($arg)) is not expected value ([set $arg])."
+ }
+ }
+ # Check refCount only if caller has specified it as non-0
+ if {$refCount && $refCount != $rep(refCount)} {
+ lappend errors "refCount in list representation ($rep(refCount)) is not expected value ($refCount)."
+ }
+ return $errors
+}
+
+proc assertListrep {l listLen numAllocated leadSpace tailSpace {refCount 0}} {
+ # Like check_listrep but raises error
+ set errors [checkListrep $l $listLen $numAllocated $leadSpace $tailSpace $refCount]
+ if {[llength $errors]} {
+ error [join $errors \n]
+ }
+ return
+}
+
+# The default length should be large enough that doubling the allocation will
+# clearly distinguish free space allocation difference between front and back.
+# (difference in the two should at least be 2 else we cannot tell if front
+# or back was favored appropriately)
+proc freeSpaceNone {{len 8}} {return [testlistrep new $len 0 0]}
+proc freeSpaceLead {{len 8} {lead 3}} {return [testlistrep new $len $lead 0]}
+proc freeSpaceTail {{len 8} {tail 3}} {return [testlistrep new $len 0 $tail]}
+proc freeSpaceBoth {{len 8} {lead 3} {tail 3}} {
+ return [testlistrep new $len $lead $tail]
+}
+proc zombieSample {{len 1000} {leadzombies 100} {tailzombies 100}} {
+ # returns an unshared listrep with zombies in front and back
+
+ # don't combine freespacenone and lrange else zombies are freed
+ set l [freeSpaceNone [expr {$len+$leadzombies+$tailzombies}]]
+ return [lrange $l $leadzombies [expr {$leadzombies+$len-1}]]
+}
+
+# Just ensure above stubs return what's expected
+if {[testConstraint testlistrep]} {
+ assertListrep [freeSpaceNone] 8 8 0 0 1
+ assertListrep [freeSpaceLead] 8 11 3 0 1
+ assertListrep [freeSpaceTail] 8 11 0 3 1
+ assertListrep [freeSpaceBoth] 8 14 3 3 1
+ assertListrep [zombieSample] 1000 1200 0 0 1
+ if {![hasSpan [zombieSample]] || [dict get [testlistrep describe [zombieSample]] span spanStart] == 0} {
+ error "zombieSample span missing or span start is at 0."
+ }
+}
+
+# Define some variables for some indices because the Tcl compiler will do some
+# operations completely in byte code if indices are literals
+set zero 0
+set one 1
+set two 2
+set four 4
+set end end
+
+#
+# Test sets:
+# 1.* - unshared internal rep, no spans, with no free space
+# 2.* - shared internal rep, no spans, with no free space
+# 3.* - unshared internal rep, spanned
+# 4.* - shared internal rep, spanned
+# 5.* - shared Tcl_Obj
+# 6.* - lists with zombie Tcl_Obj's
+
+#
+# listrep-1.* tests all operate on unshared listreps with no free space
+
+test listrep-1.1 {
+ Inserts in front of unshared list with no free space should reallocate with
+ equal free space at front and back -- linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceNone] $zero 99]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {99 0 1 2 3 4 5 6 7} 1]
+
+test listrep-1.1.1 {
+ Inserts in front of unshared list with no free space should reallocate with
+ equal free space at front and back -- lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone] $zero -1 99]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {99 0 1 2 3 4 5 6 7} 1]
+
+test listrep-1.2 {
+ Inserts at back of unshared list with no free space should allocate all
+ space at back -- linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceNone] $end 99]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 6 7 99} 0 9]
+
+test listrep-1.2.1 {
+ Inserts at back of unshared list with no free space should allocate all
+ space at back -- lset version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ lset l $end+1 99
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 6 7 99} 0 9]
+
+test listrep-1.2.2 {
+ Inserts at back of unshared list with no free space should allocate all
+ space at back -- lappend version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ lappend l 99
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 6 7 99} 0 9]
+
+test listrep-1.3 {
+ Inserts in middle of unshared list with no free space should reallocate with
+ equal free space at front and back - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceNone] $four 99]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {0 1 2 3 99 4 5 6 7} 1]
+
+test listrep-1.3.1 {
+ Inserts in middle of unshared list with no free space should reallocate with
+ equal free space at front and back - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone] $four $four-1 99]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {0 1 2 3 99 4 5 6 7} 1]
+
+test listrep-1.4 {
+ Deletes from front of small unshared list with no free space should
+ just shift up leaving room at back - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone] $zero $zero]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {1 2 3 4 5 6 7} 0 1]
+
+test listrep-1.4.1 {
+ Deletes from front of small unshared list with no free space should
+ just shift up leaving room at back - lassign version
+} -constraints testlistrep -body {
+ set l [lassign [freeSpaceNone] e]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l]
+} -result [list 0 {1 2 3 4 5 6 7} 0 1]
+
+test listrep-1.4.2 {
+ Deletes from front of small unshared list with no free space should
+ just shift up leaving room at back - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ set e [lpop l $zero]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l]
+} -result [list 0 {1 2 3 4 5 6 7} 0 1]
+
+test listrep-1.4.3 {
+ Deletes from front of small unshared list with no free space should
+ just shift up leaving room at back - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceNone] $one $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {1 2 3 4 5 6 7} 0 1]
+
+test listrep-1.4.4 {
+ Deletes from front of small unshared list with no free space should
+ just shift up leaving room at back - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceNone] $zero]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {1 2 3 4 5 6 7} 0 1]
+
+test listrep-1.5 {
+ Deletes from front of large unshared list with no free space should
+ create a span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone 1000] $zero $one]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 2 998]
+} -result [list [irange 2 999] 2 0 1]
+
+test listrep-1.5.1 {
+ Deletes from front of large unshared list with no free space should
+ create a span - lassign version
+} -constraints testlistrep -body {
+ set l [lassign [freeSpaceNone 1000] e]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
+} -result [list 0 [irange 1 999] 1 0 1]
+
+test listrep-1.5.2 {
+ Deletes from front of large unshared list with no free space should
+ create a span - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceNone 1000] $two end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 2 998]
+} -result [list [irange 2 999] 2 0 1]
+
+test listrep-1.5.3 {
+ Deletes from front of large unshared list with no free space should
+ create a span - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceNone 1000] $zero]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
+} -result [list [irange 1 999] 1 0 1]
+
+test listrep-1.5.4 {
+ Deletes from front of large unshared list with no free space should
+ create a span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone 1000]
+ set e [lpop l 0]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
+} -result [list 0 [irange 1 999] 1 0 1]
+
+test listrep-1.6 {
+ Deletes closer to front of large list should move (smaller) front segment
+ -- lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone 1000] $four $four]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
+} -result [list [concat [irange 0 3] [irange 5 999]] 1 0 1]
+
+test listrep-1.6.1 {
+ Deletes closer to front of large list should move (smaller) front segment
+ -- lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone 1000]
+ set e [lpop l $four]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 1 999]
+} -result [list 4 [concat [irange 0 3] [irange 5 999]] 1 0 1]
+
+test listrep-1.7 {
+ Deletes closer to back of large list should move (smaller) back segment
+ and will not need a span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone 1000] end-$four end-$four]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list [concat [irange 0 994] [irange 996 999]] 0 1 0]
+
+test listrep-1.7.1 {
+ Deletes closer to back of large list should move (smaller) back segment
+ and will not need a span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone 1000]
+ set e [lpop l $end-4]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list 995 [concat [irange 0 994] [irange 996 999]] 0 1 0]
+
+test listrep-1.8 {
+ Deletes at back of small unshared list should not need a span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone] end-$one end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {0 1 2 3 4 5} 0 2 0]
+
+test listrep-1.8.1 {
+ Deletes at back of small unshared list should not need a span - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceNone] $zero end-$two]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {0 1 2 3 4 5} 0 2 0]
+
+test listrep-1.8.2 {
+ Deletes at back of small unshared list should not need a span - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceNone] $end-1 $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {0 1 2 3 4 5} 0 2 0]
+
+test listrep-1.8.3 {
+ Deletes at back of small unshared list should not need a span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ set e [lpop l $end]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list 7 {0 1 2 3 4 5 6} 0 1 0]
+
+test listrep-1.9 {
+ Deletes at back of large unshared list should not need a span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceNone 1000] end-$four end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list [irange 0 994] 0 5 0]
+
+test listrep-1.9.1 {
+ Deletes at back of large unshared list should not need a span - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceNone 1000] 0 $end-5]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list [irange 0 994] 0 5 0]
+
+test listrep-1.9.2 {
+ Deletes at back of large unshared list should not need a span - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceNone 1000] end-$four $end-3 end-$two $end-1 $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list [irange 0 994] 0 5 0]
+
+test listrep-1.9.3 {
+ Deletes at back of large unshared list should not need a span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone 1000]
+ set e [lpop l $end]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list 999 [irange 0 998] 0 1 0]
+
+test listrep-1.10 {
+ no-op on unshared list should force a canonical list string - lreplace version
+} -body {
+ lreplace { 1 2 3 4 } $zero -1
+} -result {1 2 3 4}
+
+test listrep-1.10.1 {
+ no-op on unshared list should force a canonical list string - lrange version
+} -body {
+ lrange { 1 2 3 4 } $zero $end
+} -result {1 2 3 4}
+
+test listrep-1.11 {
+ Append elements to large unshared list is optimized as lappend
+ so no free space in front - lreplace version
+} -body {
+ # Note $end, not end else byte code compiler short-cuts
+ set l [lreplace [freeSpaceNone 1000] $end+1 $end+1 1000]
+ validate $l
+ list $l [leadSpace $l] [expr {[tailSpace $l] > 0}] [hasSpan $l]
+} -result [list [irange 0 1000] 0 1 0]
+
+test listrep-1.11.1 {
+ Append elements to large unshared list is optimized as lappend
+ so no free space in front - linsert version
+} -body {
+ # Note $end, not end else byte code compiler short-cuts
+ set l [linsert [freeSpaceNone 1000] $end+1 1000]
+ validate $l
+ list $l [leadSpace $l] [expr {[tailSpace $l] > 0}] [hasSpan $l]
+} -result [list [irange 0 1000] 0 1 0]
+
+test listrep-1.11.2 {
+ Append elements to large unshared list leaves no free space in front
+ - lappend version
+} -body {
+ # Note $end, not end else byte code compiler short-cuts
+ set l [freeSpaceNone 1000]
+ lappend l 1000 1001
+ validate $l
+ list $l [leadSpace $l] [expr {[tailSpace $l] > 0}] [hasSpan $l]
+} -result [list [irange 0 1001] 0 1 0]
+
+
+test listrep-1.12 {
+ Replacement of elements at front with same number elements in unshared list
+ is in-place - lreplace version
+} -body {
+ set l [lreplace [freeSpaceNone] $zero $one 10 11]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {10 11 2 3 4 5 6 7} 0 0]
+
+test listrep-1.12.1 {
+ Replacement of elements at front with same number elements in unshared list
+ is in-place - lset version
+} -body {
+ set l [freeSpaceNone]
+ lset l 0 -1
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {-1 1 2 3 4 5 6 7} 0 0]
+
+test listrep-1.13 {
+ Replacement of elements at front with fewer elements in unshared list
+ results in a spanned list with space only in front
+} -body {
+ set l [lreplace [freeSpaceNone] $zero $four 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {10 5 6 7} 4 0]
+
+test listrep-1.14 {
+ Replacement of elements at front with more elements in unshared list
+ results in a reallocated spanned list with space at front and back
+} -body {
+ set l [lreplace [freeSpaceNone] $zero $one 10 11 12]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {10 11 12 2 3 4 5 6 7} 1]
+
+test listrep-1.15 {
+ Replacement of elements in middle with same number elements in unshared list
+ is in-place - lreplace version
+} -body {
+ set l [lreplace [freeSpaceNone] $one $two 10 11]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 10 11 3 4 5 6 7} 0 0]
+
+test listrep-1.15.1 {
+ Replacement of elements in middle with same number elements in unshared list
+ is in-place - lset version
+} -body {
+ set l [freeSpaceNone]
+ lset l $two -1
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 -1 3 4 5 6 7} 0 0]
+
+test listrep-1.16 {
+ Replacement of elements in front half with fewer elements in unshared list
+ results in a spanned list with space only in front since smaller segment moved
+} -body {
+ set l [lreplace [freeSpaceNone] $one $four 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 10 5 6 7} 3 0]
+
+test listrep-1.17 {
+ Replacement of elements in back half with fewer elements in unshared list
+ results in a spanned list with space only at back
+} -body {
+ set l [lreplace [freeSpaceNone] end-$four end-$one 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 10 7} 0 3]
+
+test listrep-1.18 {
+ Replacement of elements in middle more elements in unshared list
+ results in a reallocated spanned list with space at front and back
+} -body {
+ set l [lreplace [freeSpaceNone] $one $two 10 11 12]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {0 10 11 12 3 4 5 6 7} 1]
+
+test listrep-1.19 {
+ Replacement of elements at back with same number elements in unshared list
+ is in-place - lreplace version
+} -body {
+ set l [lreplace [freeSpaceNone] $end-1 $end 10 11]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 10 11} 0 0]
+
+test listrep-1.19.1 {
+ Replacement of elements at back with same number elements in unshared list
+ is in-place - lset version
+} -body {
+ set l [freeSpaceNone]
+ lset l $end 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 6 10} 0 0]
+
+test listrep-1.20 {
+ Replacement of elements at back with fewer elements in unshared list
+ is in-place with space only at the back
+} -body {
+ set l [lreplace [freeSpaceNone] $end-2 $end 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 10} 0 2]
+
+test listrep-1.21 {
+ Replacement of elements at back with more elements in unshared list
+ allocates new representation with equal space at front and back
+} -body {
+ set l [lreplace [freeSpaceNone] $end-1 $end 10 11 12]
+ validate $l
+ list $l [spaceEqual $l]
+} -result [list {0 1 2 3 4 5 10 11 12} 1]
+
+#
+# listrep-2.* tests all operate on shared list reps with no free space. Note the
+# *list internal rep* must be shared, not only the Tcl_Obj so just assigning to
+# another variable does not suffice. The lrange construct on an variable's value
+# will do the needful.
+
+test listrep-2.1 {
+ Inserts in front of shared list with no free space should reallocate with
+ more leading space in front - linsert version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [linsert $b $zero 99]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {99 0 1 2 3 4 5 6 7} 1 1]
+
+test listrep-2.1.1 {
+ Inserts in front of shared list with no free space should reallocate with
+ more leading space in front - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $zero -1 99]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {99 0 1 2 3 4 5 6 7} 1 1]
+
+test listrep-2.2 {
+ Inserts at back of shared list with no free space should reallocate with
+ more leading space in back - linsert version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [linsert $b $end 99]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 4 5 6 7 99} 1 1]
+
+test listrep-2.2.1 {
+ Inserts at back of shared list with no free space should reallocate with
+ more leading space in back - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $end+1 end+$one 99]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 4 5 6 7 99} 1 1]
+
+test listrep-2.2.2 {
+ Inserts at back of shared list with no free space should reallocate with
+ more leading space in back - lappend version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lappend b 99]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 1 {0 1 2 3 4 5 6 7 99} 1 1]
+
+test listrep-2.2.3 {
+ Inserts at back of shared list with no free space should reallocate with
+ more leading space in back - lset version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lset b $end+1 99]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 1 {0 1 2 3 4 5 6 7 99} 1 1]
+
+test listrep-2.3 {
+ Inserts in middle of shared list with no free space should reallocate with
+ equal spacing - linsert version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [linsert $b $four 99]
+ validate $l
+ list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 99 4 5 6 7} 1 1]
+
+test listrep-2.3.1 {
+ Inserts in middle of shared list with no free space should reallocate with
+ equal spacing - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $four $four-1 99]
+ validate $l
+ list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 99 4 5 6 7} 1 1]
+
+test listrep-2.4 {
+ Deletes from front of small shared list with no free space should
+ allocate new list of exact size - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $zero $zero]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 2 {1 2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.4.1 {
+ Deletes from front of small shared list with no free space should
+ allocate new list of exact size - lremove version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lremove $b $zero $one]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 2 {2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.4.2 {
+ Deletes from front of small shared list with no free space should
+ allocate new list of exact size - lrange version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lrange $b $one $end]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 2 {1 2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.4.3 {
+ Deletes from front of small shared list with no free space should
+ allocate new list of exact size - lassign version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lassign $b e]
+ validate $l
+ list $e [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 0 2 {1 2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.4.4 {
+ Deletes from front of small shared list with no free space should
+ allocate new list of exact size - lpop version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ set e [lpop l $zero]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 0 {1 2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.5 {
+ Deletes from front of large shared list with no free space should
+ create span - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $zero $zero]
+ validate $l
+ # The listrep store should be shared among a, b, l (3 refs)
+ list [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 1 3 [irange 1 999] 1 0 0 3]
+
+test listrep-2.5.1 {
+ Deletes from front of large shared list with no free space should
+ create span - lremove version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lremove $b $zero $one]
+ validate $l
+ # The listrep store should be shared among a, b, l (3 refs)
+ list [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 1 3 [irange 2 999] 1 0 0 3]
+
+test listrep-2.5.2 {
+ Deletes from front of large shared list with no free space should
+ create span - lrange version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lrange $b $two $end]
+ validate $l
+ # The listrep store should be shared among a, b, l (3 refs)
+ list [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 1 3 [irange 2 999] 1 0 0 3]
+
+test listrep-2.5.3 {
+ Deletes from front of large shared list with no free space should
+ create span - lassign version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lassign $b e]
+ validate $l
+ # The listrep store should be shared among a, b, l (3 refs)
+ list $e [sameStore $b $l] [repStoreRefCount $b] $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 0 1 3 [irange 1 999] 1 0 0 3]
+
+test listrep-2.5.4 {
+ Deletes from front of large shared list with no free space should
+ create span - lpop version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ set e [lpop l $zero]
+ validate $l
+ # The listrep store should be shared among a, b, l (3 refs)
+ list $e $l [hasSpan $l] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 0 [irange 1 999] 1 0 0 2]
+
+test listrep-2.6 {
+ Deletes from back of small shared list with no free space should
+ allocate new list of exact size - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $end $end]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 4 5 6} 0 0 1]
+
+test listrep-2.6.1 {
+ Deletes from back of small shared list with no free space should
+ allocate new list of exact size - lremove version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lremove $b $end $end-1]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 4 5} 0 0 1]
+
+test listrep-2.6.2 {
+ Deletes from back of small shared list with no free space should
+ allocate new list of exact size - lrange version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lrange $b $zero $end-1]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 4 5 6} 0 0 1]
+
+test listrep-2.6.3 {
+ Deletes from back of small shared list with no free space should
+ allocate new list of exact size - lpop version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ set e [lpop l]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 7 {0 1 2 3 4 5 6} 0 0 1]
+
+test listrep-2.7 {
+ Deletes from back of large shared list with no free space should
+ use a span - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $end $end]
+ validate $l
+ # Note lead and tail space is 0 because original list store in a,b is used
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 3 [irange 0 998] 0 0 3]
+
+test listrep-2.7.1 {
+ Deletes from back of large shared list with no free space should
+ use a span - lremove version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lremove $b $end-1 $end]
+ validate $l
+ # Note lead and tail space is 0 because original list store in a,b is used
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 3 [irange 0 997] 0 0 3]
+
+test listrep-2.7.2 {
+ Deletes from back of large shared list with no free space should
+ use a span - lrange version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lrange $b $zero $end-1]
+ validate $l
+ # Note lead and tail space is 0 because original list store in a,b is used
+ list [repStoreRefCount $b] $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 3 [irange 0 998] 0 0 3]
+
+test listrep-2.7.3 {
+ Deletes from back of large shared list with no free space should
+ use a span - lpop version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ set e [lpop l]
+ validate $l
+ # Note lead and tail space is 0 because original list store in a,b is used
+ list $e $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 999 [irange 0 998] 0 0 2]
+
+test listrep-2.8 {
+ no-op on shared list should force a canonical list representation
+ with original unchanged - lreplace version
+} -body {
+ set l { 1 2 3 4 }
+ list [lreplace $l $zero -1] $l
+} -result [list {1 2 3 4} { 1 2 3 4 }]
+
+test listrep-2.8.1 {
+ no-op on shared list should force a canonical list representation
+ with original unchanged - lrange version
+} -body {
+ set l { 1 2 3 4 }
+ list [lrange $l $zero end] $l
+} -result [list {1 2 3 4} { 1 2 3 4 }]
+
+test listrep-2.9 {
+ Appends to back of large shared list with no free space allocates new
+ list with space only at the back - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $end+1 $end+1 1000]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
+} -result [list 2 [irange 0 1000] 0 1 1]
+
+test listrep-2.9.1 {
+ Appends to back of large shared list with no free space allocates new
+ list with space only at the back - linsert version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [linsert $b $end+1 1000 1001]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
+} -result [list 2 [irange 0 1001] 0 1 1]
+
+test listrep-2.9.2 {
+ Appends to back of large shared list with no free space allocates new
+ list with space only at the back - lappend version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ lappend l 1000
+ validate $l
+ list $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
+} -result [list [irange 0 1000] 0 1 1]
+
+test listrep-2.9.3 {
+ Appends to back of large shared list with no free space allocates new
+ list with space only at the back - lset version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone 1000]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ lset l $end+1 1000
+ validate $l
+ list $l [leadSpace $l] [expr {[tailSpace $l]>0}] [repStoreRefCount $l]
+} -result [list [irange 0 1000] 0 1 1]
+
+test listrep-2.10 {
+ Replacement of elements at front with same number in shared list results
+ in a new list store with more space in front than back - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $zero $one 10 11]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {10 11 2 3 4 5 6 7} 1 1]
+
+test listrep-2.10.1 {
+ Replacement of elements at front with same number in shared list results
+ in a new list store with no extra space - lset version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ lset l $zero 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {10 1 2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.11 {
+ Replacement of elements at front with fewer elements in shared list
+ results in a new list store with more space in front than back
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $zero $four 10]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {10 5 6 7} 1 1]
+
+test listrep-2.12 {
+ Replacement of elements at front with more elements in shared list
+ results in a new spanned list with more space in front
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $zero $one 10 11 12]
+ validate $l
+ list [repStoreRefCount $b] $l [leadSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {10 11 12 2 3 4 5 6 7} 1 1]
+
+test listrep-2.13 {
+ Replacement of elements in middle with same number in shared list results
+ in a new list store with equal space in front and back - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $one $two 10 11]
+ validate $l
+ list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
+} -result [list 2 {0 10 11 3 4 5 6 7} 1 1]
+
+test listrep-2.13.1 {
+ Replacement of elements in middle with same number in shared list results
+ in a new list store with exact allocation - lset version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ lset l $one 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 10 2 3 4 5 6 7} 0 0 1]
+
+test listrep-2.14 {
+ Replacement of elements in middle with fewer elements in shared list
+ results in a new list store with equal space
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $one 5 10]
+ validate $l
+ list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
+} -result [list 2 {0 10 6 7} 1 1]
+
+test listrep-2.15 {
+ Replacement of elements in middle with more elements in shared list
+ results in a new spanned list with space in front and back
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b $one $two 10 11 12]
+ validate $l
+ list [repStoreRefCount $b] $l [spaceEqual $l] [repStoreRefCount $l]
+} -result [list 2 {0 10 11 12 3 4 5 6 7} 1 1]
+
+test listrep-2.16 {
+ Replacement of elements at back with same number in shared list results
+ in a new list store with more space in back than front - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b end-$one $end 10 11]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 3 4 5 10 11} 1 1]
+
+test listrep-2.16.1 {
+ Replacement of elements at back with same number in shared list results
+ in a new list store with no extra - lreplace version
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set l [lrange $a $zero end]; # Ensure shared listrep
+ lset l $end 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 10} 0 0 1]
+
+test listrep-2.17 {
+ Replacement of elements at back with fewer elements in shared list
+ results in a new list store with more space in back than front
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b end-$four $end 10]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 10} 1 1]
+
+test listrep-2.18 {
+ Replacement of elements at back with more elements in shared list
+ results in a new list store with more space in back than front
+} -constraints testlistrep -body {
+ set a [freeSpaceNone]
+ set b [lrange $a $zero end]; # Ensure shared listrep
+ set l [lreplace $b end-$four $end 10]
+ validate $l
+ list [repStoreRefCount $b] $l [tailSpaceMore $l] [repStoreRefCount $l]
+} -result [list 2 {0 1 2 10} 1 1]
+
+#
+# listrep-3.* - tests on unshared spanned listreps
+
+test listrep-3.1 {
+ Inserts in front of unshared spanned list with room in front should just
+ shrink the lead space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth] $zero -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange -2 7] 1 3 1]
+
+test listrep-3.1.1 {
+ Inserts in front of unshared spanned list with room in front should just
+ shrink the lead space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $zero -1 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange -2 7] 1 3 1]
+
+test listrep-3.2 {
+ Inserts in front of unshared spanned list with insufficient room in front
+ but enough total freespace should redistribute free space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 1 10] $zero -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange -2 7] 5 4 1]
+
+test listrep-3.2.1 {
+ Inserts in front of unshared spanned list with insufficient room in front
+ but enough total freespace should redistribute free space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 10] $zero -1 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange -2 7] 5 4 1]
+
+test listrep-3.3 {
+ Inserts in front of unshared spanned list with insufficient total freespace
+ should reallocate with equal free space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 1 1] $zero -3 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange -3 7] 6 5 1]
+
+test listrep-3.3.1 {
+ Inserts in front of unshared spanned list with insufficient total freespace
+ should reallocate with equal free space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $zero -1 -3 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange -3 7] 6 5 1]
+
+test listrep-3.4 {
+ Inserts at back of unshared spanned list with room at back should not
+ reallocate - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth] $end 8]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 8] 3 2 1]
+
+test listrep-3.4.1 {
+ Inserts at back of unshared spanned list with room at back should not
+ reallocate - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $end+1 $end+1 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 9] 3 1 1]
+
+test listrep-3.4.2 {
+ Inserts at back of unshared spanned list with room at back should not
+ reallocate - lappend version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth]
+ lappend l 8 9 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 10] 3 0 1]
+
+test listrep-3.4.3 {
+ Inserts at back of unshared spanned list with room at back should not
+ reallocate - lset version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth]
+ lset l $end+1 8
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 8] 3 2 1]
+
+test listrep-3.5 {
+ Inserts at back of unshared spanned list with insufficient room in back
+ but enough total freespace should redistribute free space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 10 1] $end 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 9] 5 4 1]
+
+test listrep-3.5.1 {
+ Inserts at back of unshared spanned list with insufficient room in back
+ but enough total freespace should redistribute free space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 10 1] $end+1 $end+1 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 9] 5 4 1]
+
+test listrep-3.5.2 {
+ Inserts at back of unshared spanned list with insufficient room in back
+ but enough total freespace should redistribute free space - lappend version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 8 10 1]
+ lappend l 8 9
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 9] 5 4 1]
+
+test listrep-3.5.3 {
+ Inserts at back of unshared spanned list with insufficient room in back
+ but enough total freespace should redistribute free space - lset version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 8 10 0]
+ lset l $end+1 8
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 8] 5 4 1]
+
+test listrep-3.6 {
+ Inserts in back of unshared spanned list with insufficient total freespace
+ should reallocate with all *additional* space at back. Note this differs
+ from the insert in front case because here we realloc(). - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 1 1] $end 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 10] 1 10 1]
+
+test listrep-3.6.1 {
+ Inserts in back of unshared spanned list with insufficient total freespace
+ should reallocate with all *additional* space at back. Note this differs
+ from the insert in front case because here we realloc() - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $end+1 $end+1 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 10] 1 10 1]
+
+test listrep-3.6.2 {
+ Inserts in back of unshared spanned list with insufficient total freespace
+ should reallocate with all *additional* space at back. Note this differs
+ from the insert in front case because here we realloc() - lappend version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 8 1 1]
+ lappend l 8 9 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 10] 1 10 1]
+
+test listrep-3.6.3 {
+ Inserts in back of unshared spanned list with insufficient total freespace
+ should reallocate with all *additional* space at back. Note this differs
+ from the insert in front case because here we realloc() - lset version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ lset l $end+1 8
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 0 8] 0 9 1]
+
+test listrep-3.7 {
+ Inserts in front half of unshared spanned list with room in front should not
+ reallocate and should move front segment
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth] $one -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -2 -1 1 2 3 4 5 6 7} 1 3 1]
+
+test listrep-3.8 {
+ Inserts in front half of unshared spanned list with insufficient leading
+ space but with enough tail space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 1 5] $one -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -2 -1 1 2 3 4 5 6 7} 1 3 1]
+
+test listrep-3.8.1 {
+ Inserts in front half of unshared spanned list with insufficient leading
+ space but with enough tail space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 5] $one -1 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -2 -1 1 2 3 4 5 6 7} 1 3 1]
+
+test listrep-3.9 {
+ Inserts in front half of unshared spanned list with sufficient total
+ free space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 2 2] $one -3 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 0 1 1]
+
+test listrep-3.9.1 {
+ Inserts in front half of unshared spanned list with sufficient total
+ free space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 2 2] $one -1 -3 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 0 1 1]
+
+test listrep-3.10 {
+ Inserts in front half of unshared spanned list with insufficient total space.
+ Note use of realloc() means new space will be at the back - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 1 1] $one -3 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 1 10 1]
+
+test listrep-3.10.1 {
+ Inserts in front half of unshared spanned list with insufficient total space.
+ Note use of realloc() means new space will be at the back - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $one -1 -3 -2 -1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 -3 -2 -1 1 2 3 4 5 6 7} 1 10 1]
+
+test listrep-3.11 {
+ Inserts in back half of unshared spanned list with room in back should not
+ reallocate and should move back segment - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth] $end-$one 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]
+
+test listrep-3.11.1 {
+ Inserts in back half of unshared spanned list with room in back should not
+ reallocate and should move back segment - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $end -1 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]
+
+test listrep-3.12 {
+ Inserts in back half of unshared spanned list with insufficient tail
+ space but with enough leading space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 5 1] $end-$one 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]
+
+test listrep-3.12.1 {
+ Inserts in back half of unshared spanned list with insufficient tail
+ space but with enough leading space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 5 1] $end -1 8 9]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 7} 3 1 1]
+
+test listrep-3.13 {
+ Inserts in back half of unshared spanned list with sufficient total
+ free space - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 2 2] $end-$one 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 10 7} 0 1 1]
+
+test listrep-3.13.1 {
+ Inserts in back half of unshared spanned list with sufficient total
+ free space - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 2 2] $end -1 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 10 7} 0 1 1]
+
+test listrep-3.14 {
+ Inserts in back half of unshared spanned list with insufficient
+ total space. Note use of realloc() means new space will be at the
+ back - linsert version
+} -constraints testlistrep -body {
+ set l [linsert [freeSpaceBoth 8 1 1] $end-$one 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 10 7} 1 10 1]
+
+test listrep-3.14.1 {
+ Inserts in back half of unshared spanned list with insufficient
+ total space. Note use of realloc() means new space will be at the
+ back - lrepalce version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $end -1 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {0 1 2 3 4 5 6 8 9 10 7} 1 10 1]
+
+test listrep-3.15 {
+ Deletes from front of small unshared span list results in elements
+ moved up front and span removal - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $zero $zero]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {1 2 3 4 5 6 7} 0 7 0]
+
+test listrep-3.15.1 {
+ Deletes from front of small unshared span list results in elements
+ moved up front and span removal - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth] $zero $one]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {2 3 4 5 6 7} 0 8 0]
+
+test listrep-3.15.2 {
+ Deletes from front of small unshared span list results in elements
+ moved up front and span removal - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceBoth] $one $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {1 2 3 4 5 6 7} 0 7 0]
+
+test listrep-3.15.3 {
+ Deletes from front of small unshared span list results in elements
+ moved up front and span removal - lassign version
+} -constraints testlistrep -body {
+ set l [lassign [freeSpaceBoth] e]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list 0 {1 2 3 4 5 6 7} 0 7 0]
+
+test listrep-3.15.4 {
+ Deletes from front of small unshared span list results in elements
+ moved up front and span removal - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth]
+ set e [lpop l $zero]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {1 2 3 4 5 6 7} 0 7 0]
+
+test listrep-3.16 {
+ Deletes from front of large unshared span list results in another
+ span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 1000 10 10] $zero $one]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
+} -result [list [irange 2 999] 12 10 1]
+
+test listrep-3.16.1 {
+ Deletes from front of large unshared span list results in another
+ span - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth 1000 10 10] $zero $one]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
+} -result [list [irange 2 999] 12 10 1]
+
+test listrep-3.16.2 {
+ Deletes from front of large unshared span list results in another
+ span - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceBoth 1000 10 10] $two $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
+} -result [list [irange 2 999] 12 10 1]
+
+test listrep-3.16.3 {
+ Deletes from front of large unshared span list results in another
+ span - lassign version
+} -constraints testlistrep -body {
+ set l [lassign [freeSpaceBoth 1000 10 10] e]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 11 999]
+} -result [list 0 [irange 1 999] 11 10 1]
+
+test listrep-3.16.4 {
+ Deletes from front of large unshared span list results in another
+ span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 1000 10 10]
+ set e [lpop l $zero]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 11 999]
+} -result [list 0 [irange 1 999] 11 10 1]
+
+test listrep-3.17 {
+ Deletes from back of small unshared span list results in new store
+ without span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $end $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {0 1 2 3 4 5 6} 0 7 0]
+
+test listrep-3.17.1 {
+ Deletes from back of small unshared span list results in new store
+ without span - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth] $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {0 1 2 3 4 5 6} 0 7 0]
+
+test listrep-3.17.2 {
+ Deletes from back of small unshared span list results in new store
+ without span - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceBoth] $zero $end-1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list {0 1 2 3 4 5 6} 0 7 0]
+
+test listrep-3.17.3 {
+ Deletes from back of small unshared span list results in new store
+ without span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth]
+ set e [lpop l]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l]
+} -result [list 7 {0 1 2 3 4 5 6} 0 7 0]
+
+test listrep-3.18 {
+ Deletes from back of large unshared span list results in another
+ span - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 1000 10 10] $end-1 $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
+} -result [list [irange 0 997] 10 12 1]
+
+test listrep-3.18.1 {
+ Deletes from back of large unshared span list results in another
+ span - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth 1000 10 10] $end-1 $end]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
+} -result [list [irange 0 997] 10 12 1]
+
+test listrep-3.18.2 {
+ Deletes from back of large unshared span list results in another
+ span - lrange version
+} -constraints testlistrep -body {
+ set l [lrange [freeSpaceBoth 1000 10 10] $zero $end-2]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
+} -result [list [irange 0 997] 10 12 1]
+
+test listrep-3.18.3 {
+ Deletes from back of large unshared span list results in another
+ span - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 1000 10 10]
+ set e [lpop l]
+ validate $l
+ list $e $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 999]
+} -result [list 999 [irange 0 998] 10 11 1]
+
+test listrep-3.19 {
+ Deletes from front half of small unshared span list results in
+ movement of smaller front segment - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $one $two]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 5 6]
+} -result [list {0 3 4 5 6 7} 5 3 1]
+
+test listrep-3.19.1 {
+ Deletes from front half of small unshared span list results in
+ movement of smaller front segment - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth] $one $two]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 5 6]
+} -result [list {0 3 4 5 6 7} 5 3 1]
+
+test listrep-3.20 {
+ Deletes from front half of large unshared span list results in
+ movement of smaller front segment - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 1000 10 10] $one $two]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
+} -result [list [list 0 {*}[irange 3 999]] 12 10 1]
+
+test listrep-3.20.1 {
+ Deletes from front half of large unshared span list results in
+ movement of smaller front segment - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth 1000 10 10] $one $two]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 12 998]
+} -result [list [list 0 {*}[irange 3 999]] 12 10 1]
+
+test listrep-3.21 {
+ Deletes from back half of small unshared span list results in
+ movement of smaller back segment - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth] $end-2 $end-1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 3 6]
+} -result [list {0 1 2 3 4 7} 3 5 1]
+
+test listrep-3.21.1 {
+ Deletes from back half of small unshared span list results in
+ movement of smaller back segment - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth] $end-2 $end-1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 3 6]
+} -result [list {0 1 2 3 4 7} 3 5 1]
+
+test listrep-3.22 {
+ Deletes from back half of large unshared span list results in
+ movement of smaller back segment - lreplace version
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 1000 10 10] $end-2 $end-1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
+} -result [list [list {*}[irange 0 996] 999] 10 12 1]
+
+test listrep-3.22.1 {
+ Deletes from back half of large unshared span list results in
+ movement of smaller back segment - lremove version
+} -constraints testlistrep -body {
+ set l [lremove [freeSpaceBoth 1000 10 10] $end-2 $end-1]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [hasSpan $l 10 998]
+} -result [list [list {*}[irange 0 996] 999] 10 12 1]
+
+test listrep-3.23 {
+ Replacement of elements at front with same number elements in unshared
+ spanned list is in-place - lreplace version
+} -body {
+ set l [lreplace [freeSpaceBoth] $zero $one 10 11]
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {10 11 2 3 4 5 6 7} 3 3]
+
+test listrep-3.23.1 {
+ Replacement of elements at front with same number elements in unshared
+ spanned list is in-place - lset version
+} -body {
+ set l [freeSpaceBoth]
+ lset l $zero 10
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {10 1 2 3 4 5 6 7} 3 3]
+
+test listrep-3.24 {
+ Replacement of elements at front with fewer elements in unshared
+ spanned list expands leading space - lreplace version
+} -body {
+ set l [lreplace [freeSpaceBoth] $zero $four 10]
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {10 5 6 7} 7 3]
+
+test listrep-3.25 {
+ Replacement of elements at front with more elements in unshared
+ spanned list with sufficient leading space shrinks leading space
+} -body {
+ set l [lreplace [freeSpaceBoth] $zero $one 10 11 12]
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {10 11 12 2 3 4 5 6 7} 2 3]
+
+test listrep-3.26 {
+ Replacement of elements at front with more elements in unshared
+ spanned list with insufficient leading space but sufficient total
+ free space
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 10] $zero $one 10 11 12 13]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {10 11 12 13 2 3 4 5 6 7} 5 4 1]
+
+test listrep-3.27 {
+ Replacement of elements at front in unshared spanned list with insufficient
+ total freespace should reallocate with equal free space
+} -constraints testlistrep -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $zero $one 10 11 12 13 14]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list {10 11 12 13 14 2 3 4 5 6 7} 6 5 1]
+
+test listrep-3.28 {
+ Replacement of elements at back with same number of elements in unshared
+ spanned list is in-place - lreplace version
+} -body {
+ set l [lreplace [freeSpaceBoth] $end-1 $end 10 11]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 10 11} 3 3]
+
+test listrep-3.28.1 {
+ Replacement of elements at back with same number of elements in unshared
+ spanned list is in-place - lset version
+} -body {
+ set l [freeSpaceBoth]
+ lset l $end 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 6 10} 3 3]
+
+test listrep-3.29 {
+ Replacement of elements at back with fewer elements in unshared
+ spanned list expands tail space
+} -body {
+ set l [lreplace [freeSpaceBoth] $end-2 $end 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 10} 3 5]
+
+test listrep-3.30 {
+ Replacement of elements at back with more elements in unshared
+ spanned list with sufficient tail space shrinks tailspace
+} -body {
+ set l [lreplace [freeSpaceBoth] $end-1 $end 10 11 12]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 10 11 12} 3 2]
+
+test listrep-3.31 {
+ Replacement of elements at back with more elements in unshared spanned list
+ with insufficient tail space but enough total free space moves up the span
+} -body {
+ set l [lreplace [freeSpaceBoth 8 2 2] $end-1 $end 10 11 12 13 14]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 10 11 12 13 14} 0 1]
+
+test listrep-3.32 {
+ Replacement of elements at back with more elements in unshared spanned list
+ with insufficient total space reallocates with more room in the tail because
+ of realloc()
+} -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $end-1 $end 10 11 12 13 14]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 10 11 12 13 14} 1 10]
+
+test listrep-3.33 {
+ Replacement of elements in the middle in an unshared spanned list with
+ the same number of elements - lreplace version
+} -body {
+ set l [lreplace [freeSpaceBoth] $two $four 10 11 12]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 10 11 12 5 6 7} 3 3]
+
+test listrep-3.33.1 {
+ Replacement of elements in the middle in an unshared spanned list with
+ the same number of elements - lset version
+} -body {
+ set l [freeSpaceBoth]
+ lset l $two 10
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 10 3 4 5 6 7} 3 3]
+
+test listrep-3.34 {
+ Replacement of elements in an unshared spanned list with fewer elements
+ in the front half moves the front (smaller) segment
+} -body {
+ set l [lreplace [freeSpaceBoth] $two $four 10 11]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 10 11 5 6 7} 4 3]
+
+test listrep-3.35 {
+ Replacement of elements in an unshared spanned list with fewer elements
+ in the back half moves the tail (smaller) segment
+} -body {
+ set l [lreplace [freeSpaceBoth] $end-2 $end-1 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 10 7} 3 4]
+
+test listrep-3.36 {
+ Replacement of elements in an unshared spanned list with more elements
+ when both front and back have room should move the smaller segment
+ (front case)
+} -body {
+ set l [lreplace [freeSpaceBoth] $one $two 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 8 9 10 3 4 5 6 7} 2 3]
+
+test listrep-3.37 {
+ Replacement of elements in an unshared spanned list with more elements
+ when both front and back have room should move the smaller segment
+ (back case)
+} -body {
+ set l [lreplace [freeSpaceBoth] $end-2 $end-1 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 8 9 10 7} 3 2]
+
+test listrep-3.38 {
+ Replacement of elements in an unshared spanned list with more elements
+ when only front has room
+} -body {
+ set l [lreplace [freeSpaceBoth 8 3 1] $end-1 $end-1 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 1 2 3 4 5 8 9 10 7} 1 1]
+
+test listrep-3.39 {
+ Replacement of elements in an unshared spanned list with more elements
+ when only back has room
+} -body {
+ set l [lreplace [freeSpaceBoth 8 1 3] $one $one 8 9 10]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 8 9 10 2 3 4 5 6 7} 1 1]
+
+test listrep-3.40 {
+ Replacement of elements in an unshared spanned list with more elements
+ when neither send has enough room by itself
+} -body {
+ set l [lreplace [freeSpaceBoth] $one $one 8 9 10 11 12]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 8 9 10 11 12 2 3 4 5 6 7} 1 1]
+
+test listrep-3.41 {
+ Replacement of elements in an unshared spanned list with more elements
+ when there is not enough free space results in new allocation. The back
+ end has more space because of realloc()
+} -body {
+ set l [lreplace [freeSpaceBoth 8 1 1] $one $one 8 9 10 11 12]
+ validate $l
+ list $l [leadSpace $l] [tailSpace $l]
+} -result [list {0 8 9 10 11 12 2 3 4 5 6 7} 1 11]
+
+#
+# 4.* - tests on shared spanned lists
+
+test listrep-4.1 {
+ Inserts in front of shared spanned list with used elements in lead space
+ creates new list rep with more lead than tail space - linsert version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [linsert $spanl $zero -1]
+ validate $l
+ list $master $spanl $l [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $master] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 0 999] [irange 2 997] [list -1 {*}[irange 2 997]] 1 1 2 2 1]
+
+test listrep-4.1.1 {
+ Inserts in front of shared spanned list with used elements in lead space
+ creates new list rep with more lead than tail space - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $zero -1 -2]
+ validate $l
+ list $master $spanl $l [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $master] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 0 999] [irange 2 997] [list -2 {*}[irange 2 997]] 1 1 2 2 1]
+
+test listrep-4.2 {
+ Inserts in front of shared spanned list with orphaned leading elements
+ allocate a new list rep with more lead than tail space - linsert version
+ TODO - ideally this should garbage collect the orphans and reuse the lead space
+ but that needs a "lprepend" command else the listrep operand is shared and hence
+ orphans cannot be freed
+} -constraints testlistrep -body {
+ set master [freeSpaceLead 1000 100]
+ set spanl [lrange $master $two $end-2]
+ unset master; # So elements at 0, 1 are not used
+ set l [linsert $spanl $zero -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [list -1 {*}[irange 2 997]] 0 1 1 1 1]
+
+test listrep-4.2.1 {
+ Inserts in front of shared spanned list with orphaned leading elements
+ allocate a new list rep with more lead than tail space - lreplace version
+ TODO - ideally this should garbage collect the orphans and reuse the lead space
+ but that needs a "lprepend" command else the listrep operand is shared and hence
+ orphans cannot be freed
+} -constraints testlistrep -body {
+ set master [freeSpaceLead 1000 100]
+ set spanl [lrange $master $two $end-2]
+ unset master; # So elements at 0, 1 are not used
+ set l [lreplace $spanl $zero -1 -2]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [list -2 {*}[irange 2 997]] 0 1 1 1 1]
+
+test listrep-4.3 {
+ Inserts in front of shared spanned list where span is at front of used
+ space reuses the same list store - linsert version
+} -constraints testlistrep -body {
+ set master [freeSpaceLead 1000 100]
+ set spanl [lrange $master $zero $end-2]
+ set l [linsert $spanl $zero -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpace $l] [tailSpace $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 0 997] [irange -1 997] 1 99 0 1 3 3]
+
+test listrep-4.3.1 {
+ Inserts in front of shared spanned list where span is at front of used
+ space reuses the same list store - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceLead 1000 100]
+ set spanl [lrange $master $zero $end-2]
+ set l [lreplace $spanl $zero -1 -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpace $l] [tailSpace $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 0 997] [irange -1 997] 1 99 0 1 3 3]
+
+test listrep-4.4 {
+ Inserts in front of shared spanned list where span is at front of used
+ space allocates new listrep if lead space insufficient even if total free space
+ is sufficient. New listrep should have more lead space than tail space.
+ - linsert version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set spanl [lrange $master $zero $end-2]
+ set l [linsert $spanl $zero -3 -2 -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 0 997] [irange -3 997] 0 1 1 2 1]
+
+test listrep-4.4.1 {
+ Inserts in front of shared spanned list where span is at front of used
+ space allocates new listrep if lead space insufficient even if total free space
+ is sufficient. New listrep should have more lead space than tail space.
+ - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set spanl [lrange $master $zero $end-2]
+ set l [lreplace $spanl $zero -1 -3 -2 -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 0 997] [irange -3 997] 0 1 1 2 1]
+
+test listrep-4.5 {
+ Inserts in back of shared spanned list where span is at end of used space
+ still allocates a new listrep and trailing space is more than leading space
+ - linsert version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set spanl [lrange $master $two $end]
+ set l [linsert $spanl $end 1000]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 999] [irange 2 1000] 0 1 1 2 1]
+
+test listrep-4.5.1 {
+ Inserts in back of shared spanned list where span is at end of used space
+ still allocates a new listrep and trailing space is more than leading space
+ - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set spanl [lrange $master $two $end]
+ set l [lreplace $spanl $end+1 $end+1 1000]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 999] [irange 2 1000] 0 1 1 2 1]
+
+test listrep-4.5.2 {
+ Inserts in back of shared spanned list where span is at end of used space
+ still allocates a new listrep and trailing space is more than leading space
+ - lappend version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set l [lrange $master $two $end]
+ lappend l 1000
+ validate $l
+ list $l [sameStore $master $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $l]
+} -result [list [irange 2 1000] 0 1 1 1]
+
+test listrep-4.5.3 {
+ Inserts in back of shared spanned list where span is at end of used space
+ still allocates a new listrep and trailing space is more than leading space
+ - lset version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set l [lrange $master $two $end]
+ lset l $end+1 1000
+ validate $l
+ list $l [sameStore $master $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $l]
+} -result [list [irange 2 1000] 0 1 1 1]
+
+
+test listrep-4.6 {
+ Inserts in middle of shared spanned list allocates a new listrep with equal
+ lead and tail space - linsert version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set spanl [lrange $master $two $end-2]
+ set i 200
+ set l [linsert $spanl $i 1000]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 201] 1000 [irange 202 997]] 0 1 1 2 1]
+
+test listrep-4.6.1 {
+ Inserts in middle of shared spanned list allocates a new listrep with equal
+ lead and tail space - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceBoth 1000 2]
+ set spanl [lrange $master $two $end-2]
+ set i 200
+ set l [lreplace $spanl $i -1 1000]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 201] 1000 [irange 202 997]] 0 1 1 2 1]
+
+test listrep-4.7 {
+ Deletes from front of shared spanned list do not create a new allocation
+ - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $zero $one]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [irange 4 997] 1 1 3 3]
+
+test listrep-4.7.1 {
+ Deletes from front of shared spanned list do not create a new allocation
+ - lremove version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lremove $spanl $zero $one]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [irange 4 997] 1 1 3 3]
+
+test listrep-4.7.2 {
+ Deletes from front of shared spanned list do not create a new allocation
+ - lrange version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lrange $spanl $two $end]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [irange 4 997] 1 1 3 3]
+
+test listrep-4.7.3 {
+ Deletes from front of shared spanned list do not create a new allocation
+ - lassign version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lassign $spanl e]
+ validate $l
+ list $e $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list 2 [irange 2 997] [irange 3 997] 1 1 3 3]
+
+test listrep-4.7.4 {
+ Deletes from front of shared spanned list do not create a new allocation
+ - lpop version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set l [lrange $master $two $end-2]
+ set e [lpop l $zero]
+ validate $l
+ list $e $l [sameStore $master $l] [hasSpan $l] [repStoreRefCount $l]
+} -result [list 2 [irange 3 997] 1 1 2]
+
+test listrep-4.8 {
+ Deletes from end of shared spanned list do not create a new allocation
+ - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $end-1 $end]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [irange 2 995] 1 1 3 3]
+
+test listrep-4.8.1 {
+ Deletes from end of shared spanned list do not create a new allocation
+ - lremove version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lremove $spanl $end-1 $end]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [irange 2 995] 1 1 3 3]
+
+test listrep-4.8.2 {
+ Deletes from end of shared spanned list do not create a new allocation
+ - lrange version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lrange $spanl 0 $end-2]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [irange 2 995] 1 1 3 3]
+
+test listrep-4.8.3 {
+ Deletes from end of shared spanned list do not create a new allocation
+ - lpop version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set l [lrange $master $two $end-2]
+ set e [lpop l]
+ validate $l
+ list $e $l [sameStore $master $l] [hasSpan $l] [repStoreRefCount $l]
+} -result [list 997 [irange 2 996] 1 1 2]
+
+test listrep-4.9 {
+ Deletes from middle of shared spanned list creates a new allocation with
+ equal free space at front and back - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set i 500
+ set l [lreplace $spanl $i $i]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [spaceEqual $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 501] [irange 503 997]] 0 1 1 2 1]
+
+test listrep-4.9.1 {
+ Deletes from middle of shared spanned list creates a new allocation with
+ equal free space at front and back - lremove version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set i 500
+ set l [lremove $spanl $i $i]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [hasSpan $l] [spaceEqual $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 501] [irange 503 997]] 0 1 1 2 1]
+
+test listrep-4.9.2 {
+ Deletes from middle of shared spanned list creates a new allocation with
+ equal free space at front and back - lpop version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set l [lrange $master $two $end-2]
+ set i 500
+ set e [lpop l $i]
+ validate $l
+ list $e $l [sameStore $master $l] [hasSpan $l] [spaceEqual $l] [repStoreRefCount $l]
+} -result [list 502 [concat [irange 2 501] [irange 503 997]] 0 1 1 1]
+
+test listrep-4.10 {
+ Replacements with same number of elements at front of shared spanned list
+ create a new allocation with more space in front - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $zero $one -2 -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat {-2 -1} [irange 4 997]] 0 1 1 2 1]
+
+test listrep-4.10.1 {
+ Replacements with same number of elements at front of shared spanned list
+ create a new allocation with exact size
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set l [lrange $master $two $end-2]
+ lset l $zero -1
+ validate $l
+ list $l [sameStore $master $l] [hasSpan $l] [repStoreRefCount $l]
+} -result [list [concat {-1} [irange 3 997]] 0 0 1]
+
+test listrep-4.11 {
+ Replacements with fewer elements at front of shared spanned list
+ create a new allocation with more space in front
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $zero $one -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat {-1} [irange 4 997]] 0 1 1 2 1]
+
+test listrep-4.12 {
+ Replacements with more elements at front of shared spanned list
+ create a new allocation with more space in front
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $zero $one -3 -2 -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [leadSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat {-3 -2 -1} [irange 4 997]] 0 1 1 2 1]
+
+test listrep-4.13 {
+ Replacements with same number of elements at back of shared spanned list
+ create a new allocation with more space in back - lreplace version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $end-1 $end 1000 1001]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 995] {1000 1001}] 0 1 1 2 1]
+
+test listrep-4.13.1 {
+ Replacements with same number of elements at back of shared spanned list
+ create a new exact allocation with no span - lset version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set l [lrange $master $two $end-2]
+ lset l $end 1000
+ validate $l
+ list $l [sameStore $master $l] [tailSpace $l] [hasSpan $l] [repStoreRefCount $l]
+} -result [list [concat [irange 2 996] {1000}] 0 0 0 1]
+
+test listrep-4.14 {
+ Replacements with fewer elements at back of shared spanned list
+ create a new allocation with more space in back
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $end-1 $end 1000]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 995] {1000}] 0 1 1 2 1]
+
+test listrep-4.15 {
+ Replacements with more elements at back of shared spanned list
+ create a new allocation with more space in back
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $end-1 $end 1000 1001 1002]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [tailSpaceMore $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 995] {1000 1001 1002}] 0 1 1 2 1]
+
+test listrep-4.16 {
+ Replacements with same number of elements in middle of shared spanned list
+ create a new allocation with equal lead and tail sapce
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $one $two -2 -1]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat {2 -2 -1} [irange 5 997]] 0 1 1 2 1]
+
+test listrep-4.16.1 {
+ Replacements with same number of elements in middle of shared spanned list
+ create a new exact allocation - lset version
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set l [lrange $master $two $end-2]
+ lset l $one -2
+ validate $l
+ list $l [sameStore $master $l] [hasSpan $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [concat {2 -2} [irange 4 997]] 0 0 0 1]
+
+test listrep-4.17 {
+ Replacements with fewer elements in middle of shared spanned list
+ create a new allocation with equal lead and tail sapce
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $end-2 $end-1 1000]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 994] {1000 997}] 0 1 1 2 1]
+
+test listrep-4.18 {
+ Replacements with more elements in middle of shared spanned list
+ create a new allocation with equal lead and tail sapce
+} -constraints testlistrep -body {
+ set master [freeSpaceNone 1000]
+ set spanl [lrange $master $two $end-2]
+ set l [lreplace $spanl $end-2 $end-1 1000 1001 1002]
+ validate $l
+ list $spanl $l [sameStore $spanl $l] [spaceEqual $l] [hasSpan $l] [repStoreRefCount $spanl] [repStoreRefCount $l]
+} -result [list [irange 2 997] [concat [irange 2 994] {1000 1001 1002 997}] 0 1 1 2 1]
+
+# 5.* - tests on shared Tcl_Obj
+# Tests when Tcl_Obj is shared but listrep is not. This is to ensure that
+# checks for shared values check the Tcl_Obj reference counts in addition to
+# the list internal representation reference counts. Probably some or all
+# cases are already covered elsewhere but easier to just test than look.
+test listrep-5.1 {
+ Verify that operation on a shared Tcl_Obj with a single-ref, spanless
+ list representation only modifies the target object - lappend version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ set l2 $l
+ set same [sameStore $l $l2]
+ lappend l 8
+ list $same $l $l2 [sameStore $l $l2]
+} -result [list 1 [irange 0 8] [irange 0 7] 0]
+
+test listrep-5.1.1 {
+ Verify that operation on a shared Tcl_Obj with a single-ref, spanless
+ list representation only modifies the target object - lset version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ set l2 $l
+ set same [sameStore $l $l2]
+ lset l $end+1 8
+ list $same $l $l2 [sameStore $l $l2]
+} -result [list 1 [irange 0 8] [irange 0 7] 0]
+
+test listrep-5.1.2 {
+ Verify that operation on a shared Tcl_Obj with a single-ref, spanless
+ list representation only modifies the target object - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone]
+ set l2 $l
+ set same [sameStore $l $l2]
+ lpop l
+ list $same $l $l2 [sameStore $l $l2] [hasSpan $l]
+} -result [list 1 [irange 0 6] [irange 0 7] 0 0]
+
+test listrep-5.2 {
+ Verify that operation on a shared Tcl_Obj with a single-ref, spanned
+ list representation only modifies the target object - lappend version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 1000 10 10]
+ set l2 $l
+ set same [sameStore $l $l2]
+ lappend l 1000
+ list $same $l $l2 [sameStore $l $l2] [hasSpan $l] [hasSpan $l2]
+} -result [list 1 [irange 0 1000] [irange 0 999] 0 1 1]
+
+test listrep-5.2.1 {
+ Verify that operation on a shared Tcl_Obj with a single-ref, spanned
+ list representation only modifies the target object - lset version
+} -constraints testlistrep -body {
+ set l [freeSpaceBoth 1000 10 10]
+ set l2 $l
+ set same [sameStore $l $l2]
+ lset l $end+1 1000
+ list $same $l $l2 [sameStore $l $l2] [hasSpan $l] [hasSpan $l2]
+} -result [list 1 [irange 0 1000] [irange 0 999] 0 1 1]
+
+test listrep-5.2.2 {
+ Verify that operation on a shared Tcl_Obj with a single-ref, spanned
+ list representation only modifies the target object - lpop version
+} -constraints testlistrep -body {
+ set l [freeSpaceNone 1000]
+ set l2 $l
+ set same [sameStore $l $l2]
+ lpop l
+ list $same $l $l2 [sameStore $l $l2] [hasSpan $l] [hasSpan $l2]
+} -result [list 1 [irange 0 998] [irange 0 999] 1 1 0]
+
+#
+# 6.* - tests when lists contain zombies.
+# The list implementation does lazy freeing in some cases so the list store
+# contain Tcl_Obj's that are not actually referenced by any list (zombies).
+# These are to be freed next time the list store is modified by a list
+# operation as long as it is no longer shared.
+test listrep-6.1 {
+ Verify that zombies are freed up - linsert at front
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [linsert $l[set l {}] $zero -1]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [list -1 {*}[irange 10 209]] 1 9 10 1]
+
+test listrep-6.1.1 {
+ Verify that zombies are freed up - linsert in middle
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [linsert $l[set l {}] $one -1]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [list 10 -1 {*}[irange 11 209]] 1 9 10 1]
+
+test listrep-6.1.2 {
+ Verify that zombies are freed up - linsert at end
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [linsert $l[set l {}] $end 210]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 10 210] 1 10 9 1]
+
+test listrep-6.2 {
+ Verify that zombies are freed up - lrange version (whole)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lrange $l[set l {}] $zero $end]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 10 209] 1 10 10 1]
+
+test listrep-6.2.1 {
+ Verify that zombies are freed up - lrange version (subrange)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lrange $l[set l {}] $one $end-1]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 11 208] 1 11 11 1]
+
+test listrep-6.3 {
+ Verify that zombies are freed up - lassign version
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lassign $l[set l {}] e]
+ list $e $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 10 [irange 11 209] 1 11 10 1]
+
+test listrep-6.4 {
+ Verify that zombies are freed up - lremove version (front)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lremove $l[set l {}] $zero]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 11 209] 1 11 10 1]
+
+test listrep-6.4.1 {
+ Verify that zombies are freed up - lremove version (back)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lremove $l[set l {}] $end]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 10 208] 1 10 11 1]
+
+test listrep-6.5 {
+ Verify that zombies are freed up - lreplace at front
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lreplace $l[set l {}] $zero $one -3 -2 -1]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [list -3 -2 -1 {*}[irange 12 209]] 1 9 10 1]
+
+test listrep-6.5.1 {
+ Verify that zombies are freed up - lreplace at back
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ # set l {} is for reference counts to drop to 1
+ set l [lreplace $l[set l {}] $end-1 $end -1 -2 -3]
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [list {*}[irange 10 207] -1 -2 -3] 1 10 9 1]
+
+test listrep-6.6 {
+ Verify that zombies are freed up - lappend
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ lappend l 210
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 10 210] 1 10 9 1]
+
+test listrep-6.7 {
+ Verify that zombies are freed up - lpop version (front)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ set e [lpop l $zero]
+ list $e $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 10 [irange 11 209] 1 11 10 1]
+
+test listrep-6.7.1 {
+ Verify that zombies are freed up - lpop version (back)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ set e [lpop l]
+ list $e $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list 209 [irange 10 208] 1 10 11 1]
+
+test listrep-6.8 {
+ Verify that zombies are freed up - lset version
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ lset l $zero -1
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [list -1 {*}[irange 11 209]] 1 10 10 1]
+
+test listrep-6.8.1 {
+ Verify that zombies are freed up - lset version (back)
+} -constraints testlistrep -body {
+ set l [zombieSample 200 10 10]
+ set addr [storeAddress $l]
+ lset l $end+1 210
+ list $l [expr {$addr == [storeAddress $l]}] [leadSpace $l] [tailSpace $l] [repStoreRefCount $l]
+} -result [list [irange 10 210] 1 10 9 1]
+
+
+# All done
+::tcltest::cleanupTests
+
+return