@@ -9,106 +9,175 @@ namespace System.IO.Tests.Enumeration
9
9
{
10
10
public class AttributeTests : FileSystemTest
11
11
{
12
- private class DefaultFileAttributes : FileSystemEnumerator < string >
12
+ private class FileSystemEntryProperties
13
13
{
14
- public DefaultFileAttributes ( string directory , EnumerationOptions options )
14
+ public string FileName { get ; init ; }
15
+ public FileAttributes Attributes { get ; init ; }
16
+ public DateTimeOffset CreationTimeUtc { get ; init ; }
17
+ public bool IsDirectory { get ; init ; }
18
+ public bool IsHidden { get ; init ; }
19
+ public DateTimeOffset LastAccessTimeUtc { get ; init ; }
20
+ public DateTimeOffset LastWriteTimeUtc { get ; init ; }
21
+ public long Length { get ; init ; }
22
+ public string Directory { get ; init ; }
23
+ public string FullPath { get ; init ; }
24
+ public string SpecifiedFullPath { get ; init ; }
25
+ }
26
+
27
+ private class GetPropertiesEnumerator : FileSystemEnumerator < FileSystemEntryProperties >
28
+ {
29
+ public GetPropertiesEnumerator ( string directory , EnumerationOptions options )
15
30
: base ( directory , options )
16
- {
17
- }
31
+ { }
18
32
19
33
protected override bool ContinueOnError ( int error )
20
34
{
21
35
Assert . False ( true , $ "Should not have errored { error } ") ;
22
36
return false ;
23
37
}
24
38
25
- protected override bool ShouldIncludeEntry ( ref FileSystemEntry entry )
26
- => ! entry . IsDirectory ;
27
-
28
- protected override string TransformEntry ( ref FileSystemEntry entry )
39
+ protected override FileSystemEntryProperties TransformEntry ( ref FileSystemEntry entry )
29
40
{
30
- string path = entry . ToFullPath ( ) ;
31
- File . Delete ( path ) ;
32
-
33
- // Attributes require a stat call on Unix- ensure that we have the right attributes
34
- // even if the returned file is deleted.
35
- Assert . Equal ( FileAttributes . Normal , entry . Attributes ) ;
36
- Assert . Equal ( path , entry . ToFullPath ( ) ) ;
37
- return new string ( entry . FileName ) ;
41
+ return new FileSystemEntryProperties
42
+ {
43
+ FileName = new string ( entry . FileName ) ,
44
+ Attributes = entry . Attributes ,
45
+ CreationTimeUtc = entry . CreationTimeUtc ,
46
+ IsDirectory = entry . IsDirectory ,
47
+ IsHidden = entry . IsHidden ,
48
+ LastAccessTimeUtc = entry . LastAccessTimeUtc ,
49
+ LastWriteTimeUtc = entry . LastWriteTimeUtc ,
50
+ Length = entry . Length ,
51
+ Directory = new string ( entry . Directory ) ,
52
+ FullPath = entry . ToFullPath ( ) ,
53
+ SpecifiedFullPath = entry . ToSpecifiedFullPath ( )
54
+ } ;
38
55
}
39
56
}
40
57
41
- [ Fact ]
42
- public void FileAttributesAreExpected ( )
58
+ // The test is performed using two items with different properties (file/dir, file length)
59
+ // to check cached values from the previous entry don't leak into the non-existing entry.
60
+ [ InlineData ( "dir1" , "dir2" ) ]
61
+ [ InlineData ( "dir1" , "file2" ) ]
62
+ [ InlineData ( "dir1" , "link2" ) ]
63
+ [ InlineData ( "file1" , "file2" ) ]
64
+ [ InlineData ( "file1" , "dir2" ) ]
65
+ [ InlineData ( "file1" , "link2" ) ]
66
+ [ InlineData ( "link1" , "file2" ) ]
67
+ [ InlineData ( "link1" , "dir2" ) ]
68
+ [ InlineData ( "link1" , "link2" ) ]
69
+ [ Theory ]
70
+ public void PropertiesWhenItemNoLongerExists ( string item1 , string item2 )
43
71
{
44
72
DirectoryInfo testDirectory = Directory . CreateDirectory ( GetTestFilePath ( ) ) ;
45
- FileInfo fileOne = new FileInfo ( Path . Combine ( testDirectory . FullName , GetTestFileName ( ) ) ) ;
46
-
47
- fileOne . Create ( ) . Dispose ( ) ;
48
-
49
- if ( PlatformDetection . IsWindows )
50
- {
51
- // Archive should always be set on a new file. Clear it and other expected flags to
52
- // see that we get "Normal" as the default when enumerating.
53
-
54
- Assert . True ( ( fileOne . Attributes & FileAttributes . Archive ) != 0 ) ;
55
- fileOne . Attributes &= ~ ( FileAttributes . Archive | FileAttributes . NotContentIndexed ) ;
56
- }
57
-
58
- using ( var enumerator = new DefaultFileAttributes ( testDirectory . FullName , new EnumerationOptions ( ) ) )
59
- {
60
- Assert . True ( enumerator . MoveNext ( ) ) ;
61
- Assert . Equal ( fileOne . Name , enumerator . Current ) ;
62
- Assert . False ( enumerator . MoveNext ( ) ) ;
63
- }
64
- }
65
73
66
- private class DefaultDirectoryAttributes : FileSystemEnumerator < string >
67
- {
68
- public DefaultDirectoryAttributes ( string directory , EnumerationOptions options )
69
- : base ( directory , options )
70
- {
71
- }
74
+ FileSystemInfo item1Info = CreateItem ( testDirectory , item1 ) ;
75
+ FileSystemInfo item2Info = CreateItem ( testDirectory , item2 ) ;
72
76
73
- protected override bool ShouldIncludeEntry ( ref FileSystemEntry entry )
74
- => entry . IsDirectory ;
75
-
76
- protected override bool ContinueOnError ( int error )
77
+ using ( var enumerator = new GetPropertiesEnumerator ( testDirectory . FullName , new EnumerationOptions ( ) { AttributesToSkip = 0 } ) )
77
78
{
78
- Assert . False ( true , $ "Should not have errored { error } ") ;
79
- return false ;
79
+ // Move to the first item.
80
+ Assert . True ( enumerator . MoveNext ( ) , "Move first" ) ;
81
+ FileSystemEntryProperties entry = enumerator . Current ;
82
+
83
+ Assert . True ( entry . FileName == item1 || entry . FileName == item2 , "Unexpected item" ) ;
84
+
85
+ // Delete both items.
86
+ DeleteItem ( testDirectory , item1 ) ;
87
+ DeleteItem ( testDirectory , item2 ) ;
88
+
89
+ // Move to the second item.
90
+ FileSystemInfo expected = entry . FileName == item1 ? item2Info : item1Info ;
91
+ Assert . True ( enumerator . MoveNext ( ) , "Move second" ) ;
92
+ entry = enumerator . Current ;
93
+
94
+ // Names and paths.
95
+ Assert . Equal ( expected . Name , entry . FileName ) ;
96
+ Assert . Equal ( testDirectory . FullName , entry . Directory ) ;
97
+ Assert . Equal ( expected . FullName , entry . FullPath ) ;
98
+ Assert . Equal ( expected . FullName , entry . SpecifiedFullPath ) ;
99
+
100
+ // Values determined during enumeration.
101
+ if ( PlatformDetection . IsBrowser )
102
+ {
103
+ // For Browser, all items are typed as DT_UNKNOWN.
104
+ Assert . False ( entry . IsDirectory ) ;
105
+ Assert . Equal ( entry . FileName . StartsWith ( '.' ) ? FileAttributes . Hidden : FileAttributes . Normal , entry . Attributes ) ;
106
+ }
107
+ else
108
+ {
109
+ Assert . Equal ( expected is DirectoryInfo , entry . IsDirectory ) ;
110
+ Assert . Equal ( expected . Attributes , entry . Attributes ) ;
111
+ }
112
+
113
+ if ( PlatformDetection . IsWindows )
114
+ {
115
+ Assert . Equal ( ( expected . Attributes & FileAttributes . Hidden ) != 0 , entry . IsHidden ) ;
116
+ Assert . Equal ( expected . CreationTimeUtc , entry . CreationTimeUtc ) ;
117
+ Assert . Equal ( expected . LastAccessTimeUtc , entry . LastAccessTimeUtc ) ;
118
+ Assert . Equal ( expected . LastWriteTimeUtc , entry . LastWriteTimeUtc ) ;
119
+ if ( expected is FileInfo fileInfo )
120
+ {
121
+ Assert . Equal ( fileInfo . Length , entry . Length ) ;
122
+ }
123
+ }
124
+ else
125
+ {
126
+ // On Unix, these values were not determined during enumeration.
127
+ // Because the file was deleted, the values can no longer be retrieved and sensible defaults are returned.
128
+ Assert . Equal ( entry . FileName . StartsWith ( '.' ) , entry . IsHidden ) ;
129
+ DateTimeOffset defaultTime = new DateTimeOffset ( DateTime . FromFileTimeUtc ( 0 ) ) ;
130
+ Assert . Equal ( defaultTime , entry . CreationTimeUtc ) ;
131
+ Assert . Equal ( defaultTime , entry . LastAccessTimeUtc ) ;
132
+ Assert . Equal ( defaultTime , entry . LastWriteTimeUtc ) ;
133
+ Assert . Equal ( 0 , entry . Length ) ;
134
+ }
135
+
136
+ Assert . False ( enumerator . MoveNext ( ) , "Move final" ) ;
80
137
}
81
138
82
- protected override string TransformEntry ( ref FileSystemEntry entry )
83
- {
84
- string path = entry . ToFullPath ( ) ;
85
- Directory . Delete ( path ) ;
86
-
87
- // Attributes require a stat call on Unix- ensure that we have the right attributes
88
- // even if the returned directory is deleted.
89
- Assert . Equal ( FileAttributes . Directory , entry . Attributes ) ;
90
- Assert . Equal ( path , entry . ToFullPath ( ) ) ;
91
- return new string ( entry . FileName ) ;
92
- }
93
- }
94
-
95
- [ Fact ]
96
- public void DirectoryAttributesAreExpected ( )
97
- {
98
- DirectoryInfo testDirectory = Directory . CreateDirectory ( GetTestFilePath ( ) ) ;
99
- DirectoryInfo subDirectory = Directory . CreateDirectory ( Path . Combine ( testDirectory . FullName , GetTestFileName ( ) ) ) ;
100
-
101
- if ( PlatformDetection . IsWindows )
139
+ static FileSystemInfo CreateItem ( DirectoryInfo testDirectory , string item )
102
140
{
103
- // Clear possible extra flags to see that we get Directory
104
- subDirectory . Attributes &= ~ FileAttributes . NotContentIndexed ;
141
+ string fullPath = Path . Combine ( testDirectory . FullName , item ) ;
142
+
143
+ // use the last char to have different lengths for different files.
144
+ Assert . True ( item . EndsWith ( '1' ) || item . EndsWith ( '2' ) ) ;
145
+ int length = ( int ) item [ item . Length - 1 ] ;
146
+
147
+ if ( item . StartsWith ( "dir" ) )
148
+ {
149
+ Directory . CreateDirectory ( fullPath ) ;
150
+ var info = new DirectoryInfo ( fullPath ) ;
151
+ info . Refresh ( ) ;
152
+ return info ;
153
+ }
154
+ else if ( item . StartsWith ( "link" ) )
155
+ {
156
+ File . CreateSymbolicLink ( fullPath , new string ( '_' , length ) ) ;
157
+ var info = new FileInfo ( fullPath ) ;
158
+ info . Refresh ( ) ;
159
+ return info ;
160
+ }
161
+ else
162
+ {
163
+ File . WriteAllBytes ( fullPath , new byte [ length ] ) ;
164
+ var info = new FileInfo ( fullPath ) ;
165
+ info . Refresh ( ) ;
166
+ return info ;
167
+ }
105
168
}
106
169
107
- using ( var enumerator = new DefaultDirectoryAttributes ( testDirectory . FullName , new EnumerationOptions ( ) ) )
170
+ static void DeleteItem ( DirectoryInfo testDirectory , string item )
108
171
{
109
- Assert . True ( enumerator . MoveNext ( ) ) ;
110
- Assert . Equal ( subDirectory . Name , enumerator . Current ) ;
111
- Assert . False ( enumerator . MoveNext ( ) ) ;
172
+ string fullPath = Path . Combine ( testDirectory . FullName , item ) ;
173
+ if ( item . StartsWith ( "dir" ) )
174
+ {
175
+ Directory . Delete ( fullPath ) ;
176
+ }
177
+ else
178
+ {
179
+ File . Delete ( fullPath ) ;
180
+ }
112
181
}
113
182
}
114
183
0 commit comments