@@ -90,6 +90,122 @@ fn optionals() -> Result<()> {
9090 Ok ( ( ) )
9191}
9292
93+ #[ test]
94+ fn read_optional ( ) -> Result < ( ) > {
95+ let td = cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
96+
97+ // Test non-existent file returns None
98+ assert ! ( td. read_optional( "nonexistent" ) ?. is_none( ) ) ;
99+
100+ // Test existing file with string contents
101+ td. write ( "test.txt" , "hello world" ) ?;
102+ let contents = td. read_optional ( "test.txt" ) ?;
103+ assert ! ( contents. is_some( ) ) ;
104+ assert_eq ! ( contents. unwrap( ) , b"hello world" ) ;
105+
106+ // Test existing file with binary contents
107+ let binary_data = vec ! [ 0u8 , 1 , 2 , 254 , 255 ] ;
108+ td. write ( "test.bin" , & binary_data) ?;
109+ let contents = td. read_optional ( "test.bin" ) ?;
110+ assert ! ( contents. is_some( ) ) ;
111+ assert_eq ! ( contents. unwrap( ) , binary_data) ;
112+
113+ // Test empty file
114+ td. write ( "empty.txt" , "" ) ?;
115+ let contents = td. read_optional ( "empty.txt" ) ?;
116+ assert ! ( contents. is_some( ) ) ;
117+ assert_eq ! ( contents. unwrap( ) , b"" ) ;
118+
119+ // Test file in subdirectory
120+ td. create_dir_all ( "sub/dir" ) ?;
121+ td. write ( "sub/dir/file.txt" , "nested content" ) ?;
122+ let contents = td. read_optional ( "sub/dir/file.txt" ) ?;
123+ assert ! ( contents. is_some( ) ) ;
124+ assert_eq ! ( contents. unwrap( ) , b"nested content" ) ;
125+
126+ // Test non-existent file in existing directory
127+ assert ! ( td. read_optional( "sub/dir/missing.txt" ) ?. is_none( ) ) ;
128+
129+ // Test large file
130+ let large_data = vec ! [ b'x' ; 10000 ] ;
131+ td. write ( "large.txt" , & large_data) ?;
132+ let contents = td. read_optional ( "large.txt" ) ?;
133+ assert ! ( contents. is_some( ) ) ;
134+ assert_eq ! ( contents. unwrap( ) , large_data) ;
135+
136+ #[ cfg( not( windows) ) ]
137+ {
138+ // Test symlink to existing file
139+ td. symlink ( "test.txt" , "link_to_test" ) ?;
140+ let contents = td. read_optional ( "link_to_test" ) ?;
141+ assert ! ( contents. is_some( ) ) ;
142+ assert_eq ! ( contents. unwrap( ) , b"hello world" ) ;
143+
144+ // Test broken symlink returns None (NotFound is mapped to None)
145+ td. symlink ( "nonexistent_target" , "broken_link" ) ?;
146+ assert ! ( td. read_optional( "broken_link" ) ?. is_none( ) ) ;
147+ }
148+
149+ Ok ( ( ) )
150+ }
151+
152+ #[ test]
153+ fn read_to_string_optional ( ) -> Result < ( ) > {
154+ let td = cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
155+
156+ // Test non-existent file returns None
157+ assert ! ( td. read_to_string_optional( "nonexistent" ) ?. is_none( ) ) ;
158+
159+ // Test existing file with valid UTF-8 string
160+ td. write ( "test.txt" , "hello world" ) ?;
161+ let contents = td. read_to_string_optional ( "test.txt" ) ?;
162+ assert ! ( contents. is_some( ) ) ;
163+ assert_eq ! ( contents. unwrap( ) , "hello world" ) ;
164+
165+ // Test file with UTF-8 content including unicode
166+ let unicode_content = "Hello 世界 🌍" ;
167+ td. write ( "unicode.txt" , unicode_content) ?;
168+ let contents = td. read_to_string_optional ( "unicode.txt" ) ?;
169+ assert ! ( contents. is_some( ) ) ;
170+ assert_eq ! ( contents. unwrap( ) , unicode_content) ;
171+
172+ // Test empty file
173+ td. write ( "empty.txt" , "" ) ?;
174+ let contents = td. read_to_string_optional ( "empty.txt" ) ?;
175+ assert ! ( contents. is_some( ) ) ;
176+ assert_eq ! ( contents. unwrap( ) , "" ) ;
177+
178+ // Test file in subdirectory
179+ td. create_dir_all ( "sub/dir" ) ?;
180+ td. write ( "sub/dir/file.txt" , "nested content" ) ?;
181+ let contents = td. read_to_string_optional ( "sub/dir/file.txt" ) ?;
182+ assert ! ( contents. is_some( ) ) ;
183+ assert_eq ! ( contents. unwrap( ) , "nested content" ) ;
184+
185+ // Test non-existent file in existing directory
186+ assert ! ( td. read_to_string_optional( "sub/dir/missing.txt" ) ?. is_none( ) ) ;
187+
188+ // Test file with invalid UTF-8 should return an error
189+ let invalid_utf8 = vec ! [ 0xff , 0xfe , 0xfd ] ;
190+ td. write ( "invalid.bin" , invalid_utf8. as_slice ( ) ) ?;
191+ assert ! ( td. read_to_string_optional( "invalid.bin" ) . is_err( ) ) ;
192+
193+ #[ cfg( not( windows) ) ]
194+ {
195+ // Test symlink to existing file
196+ td. symlink ( "test.txt" , "link_to_test" ) ?;
197+ let contents = td. read_to_string_optional ( "link_to_test" ) ?;
198+ assert ! ( contents. is_some( ) ) ;
199+ assert_eq ! ( contents. unwrap( ) , "hello world" ) ;
200+
201+ // Test broken symlink returns None (NotFound is mapped to None)
202+ td. symlink ( "nonexistent_target" , "broken_link" ) ?;
203+ assert ! ( td. read_to_string_optional( "broken_link" ) ?. is_none( ) ) ;
204+ }
205+
206+ Ok ( ( ) )
207+ }
208+
93209#[ test]
94210fn ensuredir ( ) -> Result < ( ) > {
95211 let td = cap_tempfile:: tempdir ( cap_std:: ambient_authority ( ) ) ?;
0 commit comments