summaryrefslogtreecommitdiff
path: root/test/test125.tcl
blob: b4f092244ccdd21386832dcd18f20704e409078f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# See the file LICENSE for redistribution information.
#
# Copyright (c) 2009-2009 Oracle.  All rights reserved.
#
# $Id$
#
# TEST	test125
# TEST	Test cursor comparison API.
# TEST
# TEST	The cursor comparison API reports whether two cursors within
# TEST	the same database are at the same position.  It does not report
# TEST	any information about relative position.
# TEST
# TEST	1. Test two uninitialized cursors (error).
# TEST	2. Test one uninitialized cursor, one initialized (error). 
# TEST	3. Test two cursors in different databases (error).
# TEST	4. Put two cursors in the same place, test for match.  Walk
# TEST	them back and forth a bit, more matching. 
# TEST	5. Two cursors in the same spot.  Delete through one.  

proc test125 { method args } {
	global errorInfo
	source ./include.tcl
	set tnum 125

	set args [convert_args $method $args]
	set omethod [convert_method $method]

	set txnenv 0
	set eindex [lsearch -exact $args "-env"]

	# If we are using an env, then testfile should just be the db name.
	# Otherwise it is the test directory and the name.
	if { $eindex == -1 } {
		set testfile $testdir/test$tnum.db
		set testfile2 $testdir/test$tnum-2.db
		set env NULL
	} else {
		set testfile test$tnum.db
		set testfile2 test$tnum-2.db
		incr eindex
		set env [lindex $args $eindex]
		set txnenv [is_txnenv $env]
		if { $txnenv == 1 } {
			append args " -auto_commit "
		}
		set testdir [get_home $env]
	}

	set t ""
	set txn ""

	# Run the test with and without duplicates, and with and without
	# large data items. 
	foreach dupflag { "" "-dup" "-dup -dupsort" } {
		if { [is_compressed $args] && $dupflag == "-dup" } {
			puts "Skipping unsorted dups for btree with compression"
			continue
		}
		foreach bigdata { 0 1 } {
			set msg ""
			if { $bigdata == 1 } {
				set msg "with big data"
			}
			puts "Test$tnum ($method $dupflag $msg):\
			    Cursor comparison API."
			if { [llength $dupflag] > 0 } {
				if { [is_record_based $method] ||\
				    [is_rbtree $method] } {
					puts "Skipping test for method $method\
					    with duplicates."
					continue
				}
				set dups 1
			} else { 
				set dups 0
			}

			# Testdir will get reset from the env's home dir back
			# to the default if this calls something that sources
			# include.tcl, since testdir is a global.  Set it correctly
			# here each time through the loop.
			#
			if { $env != "NULL" } {
				set testdir [get_home $env]
			}
			cleanup $testdir $env

			puts "\tTest$tnum.a: Test failure cases." 
			# Open two databases.
			set db [eval {berkdb_open_noerr} -create -mode 0644 \
			    $omethod $args $dupflag {$testfile}]
			error_check_good db_open [is_valid_db $db] TRUE
			set db2 [eval {berkdb_open_noerr} -create -mode 0644 \
			    $omethod $args $dupflag {$testfile2}]
			error_check_good db2_open [is_valid_db $db2] TRUE

			# Populate the databases.
			set nentries 1000
			if { $txnenv == 1 } {
				set t [$env txn]
				error_check_good txn [is_valid_txn $t $env] TRUE
				set txn "-txn $t"
			}
			populate $db $method $t $nentries $dups $bigdata
			populate $db2 $method $t $nentries $dups $bigdata

			# Test error conditions.
			puts "\t\tTest$tnum.a1: Uninitialized cursors."
			set c1 [eval {$db cursor} $txn]
			set c2 [eval {$db cursor} $txn]
			set ret [catch {$c1 cmp $c2} res]
			error_check_good uninitialized_cursors $ret 1

			puts "\t\tTest$tnum.a2:\
			    One initialized, one uninitialized cursor."
			$c1 get -first
			set ret [catch {$c1 cmp $c2} res]
			error_check_good one_uninitialized_cursor $ret 1

			puts "\t\tTest$tnum.a3: Cursors in different databases."
			set c3 [eval {$db2 cursor} $txn]
			set ret [$c3 get -first]
			set ret [catch {$c1 cmp $c3} res]
			error_check_good cursors_in_different_databases $ret 1

			# Clean up second database - we won't be using it again.
			$c3 close
			$db2 close
			
			# Test valid conditions.  
			# 
			# Initialize second cursor to -first.  Cursor cmp should
			# match; c1 was already there. 
			puts "\tTest$tnum.b: Cursors initialized to -first."
			set ret [$c2 get -first]
			error_check_good c1_and_c2_on_first [$c1 cmp $c2] 0 

			# Walk to the end.  We should alternate between 
			# matching and not matching. 
			puts "\tTest$tnum.c: Walk cursors to the last item."
			for { set i 1 } { $i < $nentries } { incr i } {

				# First move c1; cursors won't match.
				set ret [$c1 get -next]
				error_check_bad cmp_does_not_match [$c1 cmp $c2] 0

				# Now move c2; cursors will match again. 
				set ret [$c2 get -next]
				error_check_good cmp_matches [$c1 cmp $c2] 0
			}	

			# Now do it in reverse, starting at -last and backing up. 
			puts "\tTest$tnum.d: Cursors initialized to -last."
			set ret [$c1 get -last]
			set ret [$c2 get -last]
			error_check_good c1_and_c2_on_last [$c1 cmp $c2] 0 

			puts "\tTest$tnum.e: Walk cursors back to the first item."
			for { set i 1 } { $i < $nentries } { incr i } {

				# First move c1; cursors won't match.
				set ret [$c1 get -prev]
				error_check_bad cmp_does_not_match [$c1 cmp $c2] 0

				# Now move c2; cursors will match again. 
				set ret [$c2 get -prev]
				error_check_good cmp_matches [$c1 cmp $c2] 0
			}	

			# A cursor delete leaves the cursor in the same place, so a 
			# comparison should still work.
			puts "\tTest$tnum.f:\
			    Position comparison works with cursor deletes."
			set ret [$c1 get -first]
			set ret [$c2 get -first]

			# Do the cursor walk again, deleting as we go. 
			puts "\tTest$tnum.g: Cursor walk with deletes."
			for { set i 1 } { $i < $nentries } { incr i } {

				# First move c1; cursors won't match.
				set ret [$c1 get -next]
				error_check_bad cmp_does_not_match [$c1 cmp $c2] 0

				# Now move c2; cursors will match again. 
				set ret [$c2 get -next]
				error_check_good cmp_matches [$c1 cmp $c2] 0

				# Now delete through c2; cursors should still match.
				set ret [$c2 del]
				error_check_good cmp_still_matches [$c1 cmp $c2] 0
			}	

			# Close cursors and database; commit txn.
			error_check_good c1_close [$c1 close] 0
			error_check_good c2_close [$c2 close] 0
			if { $txnenv == 1 } {
				error_check_good txn [$t commit] 0
			}
	
			error_check_good db_close [$db close] 0
		}
	}
}