@@ -1265,12 +1265,7 @@ fn open_flavors() {
1265
1265
let mut ra = OO :: new ( ) ;
1266
1266
ra. read ( true ) . append ( true ) ;
1267
1267
1268
- #[ cfg( windows) ]
1269
- let invalid_options = 87 ; // ERROR_INVALID_PARAMETER
1270
- #[ cfg( all( unix, not( target_os = "vxworks" ) ) ) ]
1271
- let invalid_options = "Invalid argument" ;
1272
- #[ cfg( target_os = "vxworks" ) ]
1273
- let invalid_options = "invalid argument" ;
1268
+ let invalid_options = "creating or truncating a file requires write or append access" ;
1274
1269
1275
1270
// Test various combinations of creation modes and access modes.
1276
1271
//
@@ -1293,10 +1288,10 @@ fn open_flavors() {
1293
1288
check ! ( c( & w) . open( & tmpdir. join( "a" ) ) ) ;
1294
1289
1295
1290
// read-only
1296
- error ! ( c( & r) . create_new( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1297
- error ! ( c( & r) . create( true ) . truncate( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1298
- error ! ( c( & r) . truncate( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1299
- error ! ( c( & r) . create( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1291
+ error_contains ! ( c( & r) . create_new( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1292
+ error_contains ! ( c( & r) . create( true ) . truncate( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1293
+ error_contains ! ( c( & r) . truncate( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1294
+ error_contains ! ( c( & r) . create( true ) . open( & tmpdir. join( "b" ) ) , invalid_options) ;
1300
1295
check ! ( c( & r) . open( & tmpdir. join( "a" ) ) ) ; // try opening the file created with write_only
1301
1296
1302
1297
// read-write
@@ -1308,21 +1303,21 @@ fn open_flavors() {
1308
1303
1309
1304
// append
1310
1305
check ! ( c( & a) . create_new( true ) . open( & tmpdir. join( "d" ) ) ) ;
1311
- error ! ( c( & a) . create( true ) . truncate( true ) . open( & tmpdir. join( "d" ) ) , invalid_options) ;
1312
- error ! ( c( & a) . truncate( true ) . open( & tmpdir. join( "d" ) ) , invalid_options) ;
1306
+ error_contains ! ( c( & a) . create( true ) . truncate( true ) . open( & tmpdir. join( "d" ) ) , invalid_options) ;
1307
+ error_contains ! ( c( & a) . truncate( true ) . open( & tmpdir. join( "d" ) ) , invalid_options) ;
1313
1308
check ! ( c( & a) . create( true ) . open( & tmpdir. join( "d" ) ) ) ;
1314
1309
check ! ( c( & a) . open( & tmpdir. join( "d" ) ) ) ;
1315
1310
1316
1311
// read-append
1317
1312
check ! ( c( & ra) . create_new( true ) . open( & tmpdir. join( "e" ) ) ) ;
1318
- error ! ( c( & ra) . create( true ) . truncate( true ) . open( & tmpdir. join( "e" ) ) , invalid_options) ;
1319
- error ! ( c( & ra) . truncate( true ) . open( & tmpdir. join( "e" ) ) , invalid_options) ;
1313
+ error_contains ! ( c( & ra) . create( true ) . truncate( true ) . open( & tmpdir. join( "e" ) ) , invalid_options) ;
1314
+ error_contains ! ( c( & ra) . truncate( true ) . open( & tmpdir. join( "e" ) ) , invalid_options) ;
1320
1315
check ! ( c( & ra) . create( true ) . open( & tmpdir. join( "e" ) ) ) ;
1321
1316
check ! ( c( & ra) . open( & tmpdir. join( "e" ) ) ) ;
1322
1317
1323
1318
// Test opening a file without setting an access mode
1324
1319
let mut blank = OO :: new ( ) ;
1325
- error ! ( blank. create( true ) . open( & tmpdir. join( "f" ) ) , invalid_options) ;
1320
+ error_contains ! ( blank. create( true ) . open( & tmpdir. join( "f" ) ) , invalid_options) ;
1326
1321
1327
1322
// Test write works
1328
1323
check ! ( check!( File :: create( & tmpdir. join( "h" ) ) ) . write( "foobar" . as_bytes( ) ) ) ;
@@ -2084,3 +2079,34 @@ fn test_rename_junction() {
2084
2079
// Junction links are always absolute so we just check the file name is correct.
2085
2080
assert_eq ! ( fs:: read_link( & dest) . unwrap( ) . file_name( ) , Some ( not_exist. as_os_str( ) ) ) ;
2086
2081
}
2082
+
2083
+ #[ test]
2084
+ fn test_open_options_invalid_combinations ( ) {
2085
+ use crate :: fs:: OpenOptions as OO ;
2086
+
2087
+ let test_cases: & [ ( fn ( ) -> OO , & str ) ] = & [
2088
+ ( || OO :: new ( ) . create ( true ) . read ( true ) . clone ( ) , "create without write" ) ,
2089
+ ( || OO :: new ( ) . create_new ( true ) . read ( true ) . clone ( ) , "create_new without write" ) ,
2090
+ ( || OO :: new ( ) . truncate ( true ) . read ( true ) . clone ( ) , "truncate without write" ) ,
2091
+ ( || OO :: new ( ) . truncate ( true ) . append ( true ) . clone ( ) , "truncate with append" ) ,
2092
+ ] ;
2093
+
2094
+ for ( make_opts, desc) in test_cases {
2095
+ let opts = make_opts ( ) ;
2096
+ let result = opts. open ( "nonexistent.txt" ) ;
2097
+ assert ! ( result. is_err( ) , "{desc} should fail" ) ;
2098
+ let err = result. unwrap_err ( ) ;
2099
+ assert_eq ! ( err. kind( ) , ErrorKind :: InvalidInput , "{desc} - wrong error kind" ) ;
2100
+ assert_eq ! (
2101
+ err. to_string( ) ,
2102
+ "creating or truncating a file requires write or append access" ,
2103
+ "{desc} - wrong error message"
2104
+ ) ;
2105
+ }
2106
+
2107
+ let result = OO :: new ( ) . open ( "nonexistent.txt" ) ;
2108
+ assert ! ( result. is_err( ) , "no access mode should fail" ) ;
2109
+ let err = result. unwrap_err ( ) ;
2110
+ assert_eq ! ( err. kind( ) , ErrorKind :: InvalidInput ) ;
2111
+ assert_eq ! ( err. to_string( ) , "must specify at least one of read, write, or append access" ) ;
2112
+ }
0 commit comments