1# See the file LICENSE for redistribution information.
2#
3# Copyright (c) 1996,2008 Oracle.  All rights reserved.
4#
5# $Id: rsrc001.tcl,v 12.6 2008/01/08 20:58:53 bostic Exp $
6#
7# TEST	rsrc001
8# TEST	Recno backing file test.  Try different patterns of adding
9# TEST	records and making sure that the corresponding file matches.
10proc rsrc001 { } {
11	source ./include.tcl
12
13	puts "Rsrc001: Basic recno backing file writeback tests"
14
15	# We run this test essentially twice, once with a db file
16	# and once without (an in-memory database).
17	set rec1 "This is record 1"
18	set rec2 "This is record 2 This is record 2"
19	set rec3 "This is record 3 This is record 3 This is record 3"
20	set rec4 [replicate "This is record 4 " 512]
21
22	foreach testfile { "$testdir/rsrc001.db" "" } {
23
24		cleanup $testdir NULL
25
26		if { $testfile == "" } {
27			puts "Rsrc001: Testing with in-memory database."
28		} else {
29			puts "Rsrc001: Testing with disk-backed database."
30		}
31
32		# Create backing file for the empty-file test.
33		set oid1 [open $testdir/rsrc.txt w]
34		close $oid1
35
36		puts "\tRsrc001.a: Put to empty file."
37		set db [eval {berkdb_open -create -mode 0644\
38		    -recno -source $testdir/rsrc.txt} $testfile]
39		error_check_good dbopen [is_valid_db $db] TRUE
40		set txn ""
41
42		set ret [eval {$db put} $txn {1 $rec1}]
43		error_check_good put_to_empty $ret 0
44		error_check_good db_close [$db close] 0
45
46		# Now fill out the backing file and create the check file.
47		set oid1 [open $testdir/rsrc.txt a]
48		set oid2 [open $testdir/check.txt w]
49
50		# This one was already put into rsrc.txt.
51		puts $oid2 $rec1
52
53		# These weren't.
54		puts $oid1 $rec2
55		puts $oid2 $rec2
56		puts $oid1 $rec3
57		puts $oid2 $rec3
58		puts $oid1 $rec4
59		puts $oid2 $rec4
60		close $oid1
61		close $oid2
62
63		puts -nonewline "\tRsrc001.b: Read file, rewrite last record;"
64		puts " write it out and diff"
65		set db [eval {berkdb_open -create -mode 0644\
66		    -recno -source $testdir/rsrc.txt} $testfile]
67		error_check_good dbopen [is_valid_db $db] TRUE
68
69		# Read the last record; replace it (but we won't change it).
70		# Then close the file and diff the two files.
71		set dbc [eval {$db cursor} $txn]
72		error_check_good db_cursor [is_valid_cursor $dbc $db] TRUE
73
74		set rec [$dbc get -last]
75		error_check_good get_last [llength [lindex $rec 0]] 2
76		set key [lindex [lindex $rec 0] 0]
77		set data [lindex [lindex $rec 0] 1]
78
79		# Get the last record from the text file
80		set oid [open $testdir/rsrc.txt]
81		set laststr ""
82		while { [gets $oid str] != -1 } {
83			set laststr $str
84		}
85		close $oid
86		set data [sanitize_record $data]
87		error_check_good getlast $data $laststr
88
89		set ret [eval {$db put} $txn {$key $data}]
90		error_check_good replace_last $ret 0
91
92		error_check_good curs_close [$dbc close] 0
93		error_check_good db_sync [$db sync] 0
94		error_check_good db_sync [$db sync] 0
95		error_check_good \
96		    Rsrc001:diff($testdir/rsrc.txt,$testdir/check.txt) \
97		    [filecmp $testdir/rsrc.txt $testdir/check.txt] 0
98
99		puts -nonewline "\tRsrc001.c: "
100		puts "Append some records in tree and verify in file."
101		set oid [open $testdir/check.txt a]
102		for {set i 1} {$i < 10} {incr i} {
103			set rec [replicate "New Record $i" $i]
104			puts $oid $rec
105			incr key
106			set ret [eval {$db put} $txn {-append $rec}]
107			error_check_good put_append $ret $key
108		}
109		error_check_good db_sync [$db sync] 0
110		error_check_good db_sync [$db sync] 0
111		close $oid
112		set ret [filecmp $testdir/rsrc.txt $testdir/check.txt]
113		error_check_good \
114		    Rsrc001:diff($testdir/{rsrc.txt,check.txt}) $ret 0
115
116		puts "\tRsrc001.d: Append by record number"
117		set oid [open $testdir/check.txt a]
118		for {set i 1} {$i < 10} {incr i} {
119			set rec [replicate "New Record (set 2) $i" $i]
120			puts $oid $rec
121			incr key
122			set ret [eval {$db put} $txn {$key $rec}]
123			error_check_good put_byno $ret 0
124		}
125
126		error_check_good db_sync [$db sync] 0
127		error_check_good db_sync [$db sync] 0
128		close $oid
129		set ret [filecmp $testdir/rsrc.txt $testdir/check.txt]
130		error_check_good \
131		    Rsrc001:diff($testdir/{rsrc.txt,check.txt}) $ret 0
132
133		puts "\tRsrc001.e: Put beyond end of file."
134		set oid [open $testdir/check.txt a]
135		for {set i 1} {$i < 10} {incr i} {
136			puts $oid ""
137			incr key
138		}
139		set rec "Last Record"
140		puts $oid $rec
141		incr key
142
143		set ret [eval {$db put} $txn {$key $rec}]
144		error_check_good put_byno $ret 0
145
146		puts "\tRsrc001.f: Put beyond end of file, after reopen."
147
148		error_check_good db_close [$db close] 0
149		set db [eval {berkdb_open -create -mode 0644\
150		    -recno -source $testdir/rsrc.txt} $testfile]
151		error_check_good dbopen [is_valid_db $db] TRUE
152
153		set rec "Last record with reopen"
154		puts $oid $rec
155
156		incr key
157		set ret [eval {$db put} $txn {$key $rec}]
158		error_check_good put_byno_with_reopen $ret 0
159
160		puts "\tRsrc001.g:\
161		    Put several beyond end of file, after reopen with snapshot."
162		error_check_good db_close [$db close] 0
163		set db [eval {berkdb_open -create -mode 0644\
164		    -snapshot -recno -source $testdir/rsrc.txt} $testfile]
165		error_check_good dbopen [is_valid_db $db] TRUE
166
167		set rec "Really really last record with reopen"
168		puts $oid ""
169		puts $oid ""
170		puts $oid ""
171		puts $oid $rec
172
173		incr key
174		incr key
175		incr key
176		incr key
177
178		set ret [eval {$db put} $txn {$key $rec}]
179		error_check_good put_byno_with_reopen $ret 0
180
181		error_check_good db_sync [$db sync] 0
182		error_check_good db_sync [$db sync] 0
183
184		close $oid
185		set ret [filecmp $testdir/rsrc.txt $testdir/check.txt]
186		error_check_good \
187		    Rsrc001:diff($testdir/{rsrc.txt,check.txt}) $ret 0
188
189		puts "\tRsrc001.h: Verify proper syncing of changes on close."
190		error_check_good Rsrc001:db_close [$db close] 0
191		set db [eval {berkdb_open -create -mode 0644 -recno \
192		    -source $testdir/rsrc.txt} $testfile]
193		set oid [open $testdir/check.txt a]
194		for {set i 1} {$i < 10} {incr i} {
195			set rec [replicate "New Record $i" $i]
196			puts $oid $rec
197			set ret [eval {$db put} $txn {-append $rec}]
198			# Don't bother checking return;  we don't know what
199			# the key number is, and we'll pick up a failure
200			# when we compare.
201		}
202		error_check_good Rsrc001:db_close [$db close] 0
203		close $oid
204		set ret [filecmp $testdir/rsrc.txt $testdir/check.txt]
205		error_check_good Rsrc001:diff($testdir/{rsrc,check}.txt) $ret 0
206	}
207}
208
209# Strip CRs from a record.
210# Needed on Windows when a file is created as text (with CR/LF)
211# but read as binary (where CR is read as a separate character)
212proc sanitize_record { rec } {
213	source ./include.tcl
214
215	if { $is_windows_test != 1 } {
216		return $rec
217	}
218	regsub -all \15 $rec "" data
219	return $data
220}
221