1set ::num_tests 0 2set ::num_passed 0 3set ::num_failed 0 4set ::tests_failed {} 5 6proc fail {msg} { 7 error "assertion:$msg" 8} 9 10proc assert {condition} { 11 if {![uplevel 1 [list expr $condition]]} { 12 error "assertion:Expected condition '$condition' to be true ([uplevel 1 [list subst -nocommands $condition]])" 13 } 14} 15 16proc assert_match {pattern value} { 17 if {![string match $pattern $value]} { 18 error "assertion:Expected '$value' to match '$pattern'" 19 } 20} 21 22proc assert_equal {expected value} { 23 if {$expected ne $value} { 24 error "assertion:Expected '$value' to be equal to '$expected'" 25 } 26} 27 28proc assert_error {pattern code} { 29 if {[catch {uplevel 1 $code} error]} { 30 assert_match $pattern $error 31 } else { 32 error "assertion:Expected an error but nothing was catched" 33 } 34} 35 36proc assert_encoding {enc key} { 37 # Swapped out values don't have an encoding, so make sure that 38 # the value is swapped in before checking the encoding. 39 set dbg [r debug object $key] 40 while {[string match "* swapped at:*" $dbg]} { 41 r debug swapin $key 42 set dbg [r debug object $key] 43 } 44 assert_match "* encoding:$enc *" $dbg 45} 46 47proc assert_type {type key} { 48 assert_equal $type [r type $key] 49} 50 51# Wait for the specified condition to be true, with the specified number of 52# max retries and delay between retries. Otherwise the 'elsescript' is 53# executed. 54proc wait_for_condition {maxtries delay e _else_ elsescript} { 55 while {[incr maxtries -1] >= 0} { 56 if {[uplevel 1 [list expr $e]]} break 57 after $delay 58 } 59 if {$maxtries == -1} { 60 uplevel 1 $elsescript 61 } 62} 63 64# Test if TERM looks like to support colors 65proc color_term {} { 66 expr {[info exists ::env(TERM)] && [string match *xterm* $::env(TERM)]} 67} 68 69proc colorstr {color str} { 70 if {[color_term]} { 71 set b 0 72 if {[string range $color 0 4] eq {bold-}} { 73 set b 1 74 set color [string range $color 5 end] 75 } 76 switch $color { 77 red {set colorcode {31}} 78 green {set colorcode {32}} 79 yellow {set colorcode {33}} 80 blue {set colorcode {34}} 81 magenta {set colorcode {35}} 82 cyan {set colorcode {36}} 83 white {set colorcode {37}} 84 default {set colorcode {37}} 85 } 86 if {$colorcode ne {}} { 87 return "\033\[$b;${colorcode};40m$str\033\[0m" 88 } 89 } else { 90 return $str 91 } 92} 93 94proc test {name code {okpattern undefined}} { 95 # abort if tagged with a tag to deny 96 foreach tag $::denytags { 97 if {[lsearch $::tags $tag] >= 0} { 98 return 99 } 100 } 101 102 # check if tagged with at least 1 tag to allow when there *is* a list 103 # of tags to allow, because default policy is to run everything 104 if {[llength $::allowtags] > 0} { 105 set matched 0 106 foreach tag $::allowtags { 107 if {[lsearch $::tags $tag] >= 0} { 108 incr matched 109 } 110 } 111 if {$matched < 1} { 112 return 113 } 114 } 115 116 incr ::num_tests 117 set details {} 118 lappend details "$name in $::curfile" 119 120 send_data_packet $::test_server_fd testing $name 121 122 if {[catch {set retval [uplevel 1 $code]} error]} { 123 if {[string match "assertion:*" $error]} { 124 set msg [string range $error 10 end] 125 lappend details $msg 126 lappend ::tests_failed $details 127 128 incr ::num_failed 129 send_data_packet $::test_server_fd err [join $details "\n"] 130 } else { 131 # Re-raise, let handler up the stack take care of this. 132 error $error $::errorInfo 133 } 134 } else { 135 if {$okpattern eq "undefined" || $okpattern eq $retval || [string match $okpattern $retval]} { 136 incr ::num_passed 137 send_data_packet $::test_server_fd ok $name 138 } else { 139 set msg "Expected '$okpattern' to equal or match '$retval'" 140 lappend details $msg 141 lappend ::tests_failed $details 142 143 incr ::num_failed 144 send_data_packet $::test_server_fd err [join $details "\n"] 145 } 146 } 147 148 if {$::traceleaks} { 149 set output [exec leaks redis-server] 150 if {![string match {*0 leaks*} $output]} { 151 send_data_packet $::test_server_fd err "Detected a memory leak in test '$name': $output" 152 } 153 } 154} 155