1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 2000,2008 Oracle.  All rights reserved.
4#
5# $Id: fop004.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	fop004
8# TEST	Test of DB->rename(). (formerly test075)
9# TEST	Test that files can be renamed from one directory to another.
10# TEST	Test that files can be renamed using absolute or relative
11# TEST	pathnames.
12proc fop004 { method { tnum "004" } args } {
13	global encrypt
14	global errorCode
15	global errorInfo
16	source ./include.tcl
17
18	set args [convert_args $method $args]
19	set omethod [convert_method $method]
20
21	puts "Fop$tnum: ($method $args): Test of DB->rename()"
22
23	set eindex [lsearch -exact $args "-env"]
24	if { $eindex != -1 } {
25		# If we are using an env, then skip this test.
26		# It needs its own.
27		incr eindex
28		set env [lindex $args $eindex]
29		puts "Skipping fop$tnum for env $env"
30		return
31	}
32	if { $encrypt != 0 } {
33		puts "Skipping fop$tnum for security"
34		return
35	}
36	cleanup $testdir NULL
37
38	# Define absolute pathnames
39	set curdir [pwd]
40	cd $testdir
41	set fulldir [pwd]
42	cd $curdir
43	set reldir $testdir
44
45	# Name subdirectories for renaming from one directory to another.
46	set subdira A
47	set subdirb B
48
49	# Set up absolute and relative pathnames for test
50	set paths [list "absolute $fulldir" "relative $reldir"]
51	set files [list "fop$tnum-old.db fop$tnum-new.db {name change}" \
52	    "fop$tnum.db fop$tnum.db {directory change}"]
53
54	foreach pathinfo $paths {
55		set pathtype [lindex $pathinfo 0]
56		set path [lindex $pathinfo 1]
57		foreach fileinfo $files {
58			set desc [lindex $fileinfo 2]
59			puts "Fop$tnum: Test of $pathtype path $path with $desc"
60			set env NULL
61			set envargs ""
62
63			# Loop through test using the following rename options
64			# 1. no environment, not in transaction
65			# 2. with environment, not in transaction
66			# 3. rename with auto-commit
67			# 4. rename in committed transaction
68			# 5. rename in aborted transaction
69
70			foreach op "noenv env auto commit abort" {
71
72				puts "\tFop$tnum.a: Create/rename with $op"
73				# If we are using an env, then testfile should
74				# be the db name.  Otherwise it is the path we
75				# are testing and the name.
76				#
77				set old [lindex $fileinfo 0]
78				set new [lindex $fileinfo 1]
79				# Set up subdirectories if necessary.
80				if { $desc == "directory change" } {
81					file mkdir $testdir/$subdira
82					file mkdir $testdir/$subdirb
83					set oldname $subdira/$old
84					set newname $subdirb/$new
85					set oldextent $subdira/__dbq.$old.0
86					set newextent $subdirb/__dbq.$new.0
87				} else {
88					set oldname $old
89					set newname $new
90					set oldextent __dbq.$old.0
91					set newextent __dbq.$new.0
92				}
93				# If we don't have an env, we're going to
94				# operate on the file using its absolute
95				# or relative path.  Tack it on the front.
96				if { $op == "noenv" } {
97					set oldfile $path/$oldname
98					set newfile $path/$newname
99					set oldextent $path/$oldextent
100					set newextent $path/$newextent
101				} else {
102					set oldfile $oldname
103					set newfile $newname
104					set txnarg ""
105					if { $op == "auto" || $op == "commit" \
106					    || $op == "abort" } {
107						set txnarg " -txn"
108					}
109					set env [eval {berkdb_env -create} \
110					    $txnarg -home $path]
111					set envargs "-env $env"
112					error_check_good \
113					    env_open [is_valid_env $env] TRUE
114				}
115
116				# Files don't exist before starting the test.
117				#
118				check_file_exist $oldfile $env $path 0
119				check_file_exist $newfile $env $path 0
120
121				puts "\t\tFop$tnum.a.1: Create file $oldfile"
122				set db [eval {berkdb_open -create -mode 0644} \
123				    $omethod $envargs $args $oldfile]
124				error_check_good dbopen [is_valid_db $db] TRUE
125
126				# Use numeric key so record-based methods
127				# don't need special treatment.
128				set key 1
129				set data data
130
131				error_check_good dbput \
132				    [$db put $key [chop_data $method $data]] 0
133				error_check_good dbclose [$db close] 0
134
135				puts "\t\tFop$tnum.a.2:\
136				    Rename file to $newfile"
137				check_file_exist $oldfile $env $path 1
138				check_file_exist $newfile $env $path 0
139
140				# Regular renames use berkdb dbrename
141				# Txn-protected renames use $env dbrename.
142				if { $op == "noenv" || $op == "env" } {
143					error_check_good rename [eval \
144					    {berkdb dbrename} $envargs \
145					    $oldfile $newfile] 0
146				} elseif { $op == "auto" } {
147					error_check_good rename [eval \
148					    {$env dbrename} -auto_commit \
149					    $oldfile $newfile] 0
150				} else {
151					# $op is "abort" or "commit"
152					set txn [$env txn]
153					error_check_good rename [eval \
154					    {$env dbrename} -txn $txn \
155					    $oldfile $newfile] 0
156					error_check_good txn_$op [$txn $op] 0
157				}
158
159				if { $op != "abort" } {
160					check_file_exist $oldfile $env $path 0
161					check_file_exist $newfile $env $path 1
162				} else {
163					check_file_exist $oldfile $env $path 1
164					check_file_exist $newfile $env $path 0
165				}
166
167				# Check that extent files moved too, unless
168				# we aborted the rename.
169				if { [is_queueext $method ] == 1 } {
170					if { $op != "abort" } {
171						check_file_exist \
172						    $oldextent $env $path 0
173						check_file_exist \
174						    $newextent $env $path 1
175					} else {
176						check_file_exist \
177						    $oldextent $env $path 1
178						check_file_exist \
179						    $newextent $env $path 0
180					}
181				}
182
183				puts "\t\tFop$tnum.a.3: Check file contents"
184				# Open again with create to make sure we're not
185				# caching.  In the normal case (no env), we
186				# already know the file doesn't exist.
187				set odb [eval {berkdb_open -create -mode 0644} \
188				    $envargs $omethod $args $oldfile]
189				set ndb [eval {berkdb_open -create -mode 0644} \
190				    $envargs $omethod $args $newfile]
191				error_check_good \
192				    odb_open [is_valid_db $odb] TRUE
193				error_check_good \
194				    ndb_open [is_valid_db $ndb] TRUE
195
196				# The DBT from the "old" database should be
197				# empty, not the "new" one, except in the case
198				# of an abort.
199				set odbt [$odb get $key]
200				if { $op == "abort" } {
201					error_check_good \
202					    odbt_has_data [llength $odbt] 1
203				} else {
204					set ndbt [$ndb get $key]
205					error_check_good \
206					    odbt_empty [llength $odbt] 0
207					error_check_bad \
208					    ndbt_empty [llength $ndbt] 0
209					error_check_good ndbt \
210					    [lindex [lindex $ndbt 0] 1] \
211					    [pad_data $method $data]
212				}
213				error_check_good odb_close [$odb close] 0
214				error_check_good ndb_close [$ndb close] 0
215
216				# Now there's both an old and a new.  Rename the
217				# "new" to the "old" and make sure that fails.
218				#
219				puts "\tFop$tnum.b: Make sure rename fails\
220				    instead of overwriting"
221				set envargs ""
222				if { $env != "NULL" } {
223					error_check_good \
224					    env_close [$env close] 0
225					set env [berkdb_env_noerr -home $path]
226					set envargs " -env $env"
227					error_check_good env_open2 \
228					    [is_valid_env $env] TRUE
229				}
230				set ret [catch {eval {berkdb dbrename} \
231		    	    	    $envargs $newfile $oldfile} res]
232				error_check_bad rename_overwrite $ret 0
233				error_check_good rename_overwrite_ret \
234				    [is_substr $errorCode EEXIST] 1
235
236				# Verify and then start over from a clean slate.
237				verify_dir $path "\tFop$tnum.c: "
238				verify_dir $path/$subdira "\tFop$tnum.c: "
239				verify_dir $path/$subdirb "\tFop$tnum.c: "
240				if { $env != "NULL" } {
241					error_check_good \
242					    env_close2 [$env close] 0
243				}
244				env_cleanup $path
245				check_file_exist $oldfile $env $path 0
246				check_file_exist $newfile $env $path 0
247			}
248		}
249	}
250}
251
252proc check_file_exist { filename env path expected } {
253	if { $env != "NULL" } {
254		error_check_good "$filename exists in env" \
255		    [file exists $path/$filename] $expected
256	} else {
257		error_check_good \
258		    "$filename exists" [file exists $filename] $expected
259	}
260}
261