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 {detail ""}} { 23 if {$expected ne $value} { 24 if {$detail ne ""} { 25 set detail " (detail: $detail)" 26 } 27 error "assertion:Expected '$value' to be equal to '$expected'$detail" 28 } 29} 30 31proc assert_error {pattern code} { 32 if {[catch {uplevel 1 $code} error]} { 33 assert_match $pattern $error 34 } else { 35 error "assertion:Expected an error but nothing was caught" 36 } 37} 38 39proc assert_encoding {enc key} { 40 # Swapped out values don't have an encoding, so make sure that 41 # the value is swapped in before checking the encoding. 42 set dbg [r debug object $key] 43 while {[string match "* swapped at:*" $dbg]} { 44 r debug swapin $key 45 set dbg [r debug object $key] 46 } 47 assert_match "* encoding:$enc *" $dbg 48} 49 50proc assert_type {type key} { 51 assert_equal $type [r type $key] 52} 53 54# Wait for the specified condition to be true, with the specified number of 55# max retries and delay between retries. Otherwise the 'elsescript' is 56# executed. 57proc wait_for_condition {maxtries delay e _else_ elsescript} { 58 while {[incr maxtries -1] >= 0} { 59 set errcode [catch {uplevel 1 [list expr $e]} result] 60 if {$errcode == 0} { 61 if {$result} break 62 } else { 63 return -code $errcode $result 64 } 65 after $delay 66 } 67 if {$maxtries == -1} { 68 set errcode [catch [uplevel 1 $elsescript] result] 69 return -code $errcode $result 70 } 71} 72 73proc test {name code {okpattern undefined}} { 74 # abort if tagged with a tag to deny 75 foreach tag $::denytags { 76 if {[lsearch $::tags $tag] >= 0} { 77 return 78 } 79 } 80 81 # check if tagged with at least 1 tag to allow when there *is* a list 82 # of tags to allow, because default policy is to run everything 83 if {[llength $::allowtags] > 0} { 84 set matched 0 85 foreach tag $::allowtags { 86 if {[lsearch $::tags $tag] >= 0} { 87 incr matched 88 } 89 } 90 if {$matched < 1} { 91 return 92 } 93 } 94 95 incr ::num_tests 96 set details {} 97 lappend details "$name in $::curfile" 98 99 send_data_packet $::test_server_fd testing $name 100 101 if {[catch {set retval [uplevel 1 $code]} error]} { 102 if {[string match "assertion:*" $error]} { 103 set msg [string range $error 10 end] 104 lappend details $msg 105 lappend ::tests_failed $details 106 107 incr ::num_failed 108 send_data_packet $::test_server_fd err [join $details "\n"] 109 } else { 110 # Re-raise, let handler up the stack take care of this. 111 error $error $::errorInfo 112 } 113 } else { 114 if {$okpattern eq "undefined" || $okpattern eq $retval || [string match $okpattern $retval]} { 115 incr ::num_passed 116 send_data_packet $::test_server_fd ok $name 117 } else { 118 set msg "Expected '$okpattern' to equal or match '$retval'" 119 lappend details $msg 120 lappend ::tests_failed $details 121 122 incr ::num_failed 123 send_data_packet $::test_server_fd err [join $details "\n"] 124 } 125 } 126 127 if {$::traceleaks} { 128 set output [exec leaks redis-server] 129 if {![string match {*0 leaks*} $output]} { 130 send_data_packet $::test_server_fd err "Detected a memory leak in test '$name': $output" 131 } 132 } 133} 134