win32-file-stat 1.3.6 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,92 @@
1
+ require 'ffi'
2
+
3
+ module Windows
4
+ module Stat
5
+ module Constants
6
+ private
7
+
8
+ MAX_PATH = 260
9
+ MAXDWORD = 0xFFFFFFFF
10
+
11
+ # Normally just FFI::Pointer.new(-1).address, but we need JRuby to work, too.
12
+ INVALID_HANDLE_VALUE = (1<<FFI::Platform::ADDRESS_SIZE)-1
13
+
14
+ ERROR_FILE_NOT_FOUND = 2
15
+ ERROR_NO_MORE_FILES = 18
16
+ ERROR_INSUFFICIENT_BUFFER = 122
17
+
18
+ FILE_TYPE_UNKNOWN = 0x0000
19
+ FILE_TYPE_DISK = 0x0001
20
+ FILE_TYPE_CHAR = 0x0002
21
+ FILE_TYPE_PIPE = 0x0003
22
+ FILE_TYPE_REMOTE = 0x8000
23
+
24
+ FILE_ATTRIBUTE_READONLY = 0x00000001
25
+ FILE_ATTRIBUTE_HIDDEN = 0x00000002
26
+ FILE_ATTRIBUTE_SYSTEM = 0x00000004
27
+ FILE_ATTRIBUTE_DIRECTORY = 0x00000010
28
+ FILE_ATTRIBUTE_ARCHIVE = 0x00000020
29
+ FILE_ATTRIBUTE_ENCRYPTED = 0x00000040
30
+ FILE_ATTRIBUTE_NORMAL = 0x00000080
31
+ FILE_ATTRIBUTE_TEMPORARY = 0x00000100
32
+ FILE_ATTRIBUTE_SPARSE_FILE = 0x00000200
33
+ FILE_ATTRIBUTE_REPARSE_POINT = 0x00000400
34
+ FILE_ATTRIBUTE_COMPRESSED = 0x00000800
35
+ FILE_ATTRIBUTE_OFFLINE = 0x00001000
36
+
37
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000
38
+
39
+ DRIVE_REMOVABLE = 2
40
+ DRIVE_CDROM = 5
41
+ DRIVE_RAMDISK = 6
42
+
43
+ NO_ERROR = 0
44
+
45
+ OPEN_EXISTING = 3
46
+ GENERIC_READ = 0x80000000
47
+ GENERIC_WRITE = 0x40000000
48
+ GENERIC_EXECUTE = 0x20000000
49
+
50
+ FILE_SHARE_READ = 1
51
+
52
+ FILE_FLAG_BACKUP_SEMANTICS = 0x02000000
53
+ FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000
54
+ IO_REPARSE_TAG_SYMLINK = 0xA000000C
55
+
56
+ OWNER_SECURITY_INFORMATION = 1
57
+ GROUP_SECURITY_INFORMATION = 2
58
+ DACL_SECURITY_INFORMATION = 4
59
+
60
+ SYNCHRONIZE = 0x00100000
61
+ STANDARD_RIGHTS_REQUIRED = 0x000F0000
62
+
63
+ FILE_READ_DATA = 0x0001
64
+ FILE_WRITE_DATA = 0x0002
65
+ FILE_APPEND_DATA = 0x0004
66
+ FILE_READ_EA = 0x0008
67
+ FILE_WRITE_EA = 0x0008
68
+ FILE_EXECUTE = 0x0020
69
+ FILE_READ_ATTRIBUTES = 0x0080
70
+ FILE_WRITE_ATTRIBUTES = 0x0100
71
+
72
+ READ_CONTROL = 0x00020000
73
+ STANDARD_RIGHTS_READ = READ_CONTROL
74
+ STANDARD_RIGHTS_WRITE = READ_CONTROL
75
+ STANDARD_RIGHTS_EXECUTE = READ_CONTROL
76
+
77
+ FILE_GENERIC_READ = (STANDARD_RIGHTS_READ|FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA|SYNCHRONIZE)
78
+ FILE_GENERIC_WRITE = (STANDARD_RIGHTS_WRITE|FILE_WRITE_DATA|FILE_WRITE_ATTRIBUTES|FILE_WRITE_EA|FILE_APPEND_DATA|SYNCHRONIZE)
79
+ FILE_GENERIC_EXECUTE = (STANDARD_RIGHTS_EXECUTE|FILE_READ_ATTRIBUTES|FILE_EXECUTE|SYNCHRONIZE)
80
+ FILE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED|SYNCHRONIZE|0x1FF)
81
+
82
+ TOKEN_DUPLICATE = 0x0002
83
+ TOKEN_IMPERSONATE = 0x0004
84
+ TOKEN_QUERY = 0x0008
85
+
86
+ SecurityImpersonation = 2
87
+
88
+ TokenUser = 1
89
+ TokenGroups = 2
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,57 @@
1
+ require 'ffi'
2
+
3
+ module Windows
4
+ module Stat
5
+ module Functions
6
+ extend FFI::Library
7
+
8
+ # Wrapper method for attach_pfunc + private
9
+ def self.attach_pfunc(*args)
10
+ attach_function(*args)
11
+ private args[0]
12
+ end
13
+
14
+ typedef :ulong, :dword
15
+ typedef :uintptr_t, :handle
16
+ typedef :pointer, :ptr
17
+ typedef :buffer_in, :buf_in
18
+ typedef :string, :str
19
+
20
+ ffi_convention :stdcall
21
+
22
+ ffi_lib :kernel32
23
+
24
+ attach_pfunc :CloseHandle, [:handle], :bool
25
+ attach_pfunc :CreateFile, :CreateFileW, [:buf_in, :dword, :dword, :ptr, :dword, :dword, :handle], :handle
26
+ attach_pfunc :FindFirstFile, :FindFirstFileW, [:buf_in, :ptr], :handle
27
+ attach_pfunc :FindClose, [:handle], :bool
28
+ attach_pfunc :GetCurrentProcess, [], :handle
29
+ attach_pfunc :GetDiskFreeSpace, :GetDiskFreeSpaceW, [:buf_in, :ptr, :ptr, :ptr, :ptr], :bool
30
+ attach_pfunc :GetDriveType, :GetDriveTypeW, [:buf_in], :uint
31
+ attach_pfunc :GetFileInformationByHandle, [:handle, :ptr], :bool
32
+ attach_pfunc :GetFileType, [:handle], :dword
33
+ attach_pfunc :OpenProcessToken, [:handle, :dword, :ptr], :bool
34
+
35
+ ffi_lib :shlwapi
36
+
37
+ attach_pfunc :PathGetDriveNumber, :PathGetDriveNumberW, [:buf_in], :int
38
+ attach_pfunc :PathIsUNC, :PathIsUNCW, [:buf_in], :bool
39
+ attach_pfunc :PathStripToRoot, :PathStripToRootW, [:ptr], :bool
40
+
41
+ ffi_lib :advapi32
42
+
43
+ attach_pfunc :ConvertSidToStringSid, :ConvertSidToStringSidA, [:ptr, :ptr], :bool
44
+ attach_pfunc :ConvertStringSidToSid, :ConvertStringSidToSidA, [:ptr, :ptr], :bool
45
+ attach_pfunc :GetFileSecurity, :GetFileSecurityW, [:buf_in, :int, :ptr, :dword, :ptr], :bool
46
+ attach_pfunc :GetSecurityDescriptorOwner, [:ptr, :ptr, :ptr], :bool
47
+ attach_pfunc :GetSecurityDescriptorGroup, [:ptr, :ptr, :ptr], :bool
48
+ attach_pfunc :GetTokenInformation, [:handle, :int, :ptr, :dword, :ptr], :bool
49
+ attach_pfunc :DuplicateToken, [:handle, :dword, :ptr], :bool
50
+ attach_pfunc :MapGenericMask, [:ptr, :ptr], :void
51
+ attach_pfunc :AccessCheck, [:ptr, :handle, :dword, :ptr, :ptr, :ptr, :ptr, :ptr], :bool
52
+ attach_pfunc :BuildTrusteeWithSid, :BuildTrusteeWithSidW, [:ptr, :ptr], :void
53
+ attach_pfunc :GetSecurityDescriptorDacl, [:ptr, :ptr, :ptr, :ptr], :bool
54
+ attach_pfunc :GetEffectiveRightsFromAcl, :GetEffectiveRightsFromAclW, [:ptr, :ptr, :ptr], :dword
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,13 @@
1
+ class String
2
+ # Convenience method for converting strings to UTF-16LE for wide character
3
+ # functions that require it.
4
+ def wincode
5
+ (self.tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode('UTF-16LE')
6
+ end
7
+
8
+ # Read a wide character string up until the first double null, and delete
9
+ # any remaining null characters.
10
+ def read_wide
11
+ self[/^.*?(?=\x00{2})/].delete(0.chr)
12
+ end
13
+ end
@@ -0,0 +1,165 @@
1
+ require File.join(File.dirname(__FILE__), 'constants')
2
+
3
+ require 'ffi'
4
+
5
+ module Windows
6
+ module Stat
7
+ module Structs
8
+ extend FFI::Library
9
+
10
+ private
11
+
12
+ class LowHigh < FFI::Struct
13
+ layout(:LowPart, :ulong, :HighPart, :ulong)
14
+ end
15
+
16
+ class ULARGE_INTEGER < FFI::Union
17
+ layout(:u, LowHigh, :QuadPart, :ulong_long)
18
+ end
19
+
20
+ class FILETIME < FFI::Struct
21
+ layout(:dwLowDateTime, :ulong, :dwHighDateTime, :ulong)
22
+ end
23
+
24
+ class BY_HANDLE_FILE_INFORMATION < FFI::Struct
25
+ include Windows::Stat::Constants
26
+
27
+ layout(
28
+ :dwFileAttributes, :ulong,
29
+ :ftCreationTime, FILETIME,
30
+ :ftLastAccessTime, FILETIME,
31
+ :ftLastWriteTime, FILETIME,
32
+ :dwVolumeSerialNumber, :ulong,
33
+ :nFileSizeHigh, :ulong,
34
+ :nFileSizeLow, :ulong,
35
+ :nNumberOfLinks, :ulong,
36
+ :nFileIndexHigh, :ulong,
37
+ :nFileIndexLow, :ulong
38
+ )
39
+
40
+ # Return the atime as a number
41
+ def atime
42
+ date = ULARGE_INTEGER.new
43
+ date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
44
+ date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
45
+ date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
46
+ end
47
+
48
+ # Return the ctime as a number
49
+ def ctime
50
+ date = ULARGE_INTEGER.new
51
+ date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
52
+ date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
53
+ date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
54
+ end
55
+
56
+ # Return the mtime as a number
57
+ def mtime
58
+ date = ULARGE_INTEGER.new
59
+ date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
60
+ date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
61
+ date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
62
+ end
63
+
64
+ # Return the size as a single number
65
+ def size
66
+ (self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
67
+ end
68
+ end
69
+
70
+ class WIN32_FIND_DATA < FFI::Struct
71
+ include Windows::Stat::Constants
72
+
73
+ layout(
74
+ :dwFileAttributes, :ulong,
75
+ :ftCreationTime, FILETIME,
76
+ :ftLastAccessTime, FILETIME,
77
+ :ftLastWriteTime, FILETIME,
78
+ :nFileSizeHigh, :ulong,
79
+ :nFileSizeLow, :ulong,
80
+ :dwReserved0, :ulong,
81
+ :dwReserved1, :ulong,
82
+ :cFileName, [:uint8, MAX_PATH*2],
83
+ :cAlternateFileName, [:uint8, 28]
84
+ )
85
+
86
+ # Return the atime as a number
87
+ def atime
88
+ date = ULARGE_INTEGER.new
89
+ date[:u][:LowPart] = self[:ftLastAccessTime][:dwLowDateTime]
90
+ date[:u][:HighPart] = self[:ftLastAccessTime][:dwHighDateTime]
91
+ return 0 if date[:QuadPart]==0
92
+ date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
93
+ end
94
+
95
+ # Return the ctime as a number
96
+ def ctime
97
+ date = ULARGE_INTEGER.new
98
+ date[:u][:LowPart] = self[:ftCreationTime][:dwLowDateTime]
99
+ date[:u][:HighPart] = self[:ftCreationTime][:dwHighDateTime]
100
+ return 0 if date[:QuadPart]==0
101
+ date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
102
+ end
103
+
104
+ # Return the mtime as a number
105
+ def mtime
106
+ date = ULARGE_INTEGER.new
107
+ date[:u][:LowPart] = self[:ftLastWriteTime][:dwLowDateTime]
108
+ date[:u][:HighPart] = self[:ftLastWriteTime][:dwHighDateTime]
109
+ return 0 if date[:QuadPart]==0
110
+ date[:QuadPart] / 10000000 - 11644473600 # ns, 100-ns since Jan 1, 1601.
111
+ end
112
+
113
+ # Return the size as a single number
114
+ def size
115
+ (self[:nFileSizeHigh] * (MAXDWORD + 1)) + self[:nFileSizeLow]
116
+ end
117
+ end
118
+
119
+ class SID_AND_ATTRIBUTES < FFI::Struct
120
+ layout(:Sid, :pointer, :Attributes, :ulong)
121
+ end
122
+
123
+ class TOKEN_GROUP < FFI::Struct
124
+ layout(
125
+ :GroupCount, :ulong,
126
+ :Groups, [SID_AND_ATTRIBUTES, 128]
127
+ )
128
+ end
129
+
130
+ class GENERIC_MAPPING < FFI::Struct
131
+ layout(
132
+ :GenericRead, :ulong,
133
+ :GenericWrite, :ulong,
134
+ :GenericExecute, :ulong,
135
+ :GenericAll, :ulong
136
+ )
137
+ end
138
+
139
+ class LUID_AND_ATTRIBUTES < FFI::Struct
140
+ layout(
141
+ :Luid, LowHigh,
142
+ :Attributes, :ulong
143
+ )
144
+ end
145
+
146
+ class PRIVILEGE_SET < FFI::Struct
147
+ layout(
148
+ :PrivilegeCount, :ulong,
149
+ :Control, :ulong,
150
+ :Privilege, [LUID_AND_ATTRIBUTES, 1]
151
+ )
152
+ end
153
+
154
+ class TRUSTEE < FFI::Struct
155
+ layout(
156
+ :pMultipleTrustee, :pointer,
157
+ :MultipleTrusteeOperation, :ulong,
158
+ :TrusteeForm, :ulong,
159
+ :TrusteeType, :ulong,
160
+ :ptstrName, :pointer
161
+ )
162
+ end
163
+ end
164
+ end
165
+ end
@@ -1,354 +1,647 @@
1
- #####################################################################
2
- # test_file_stat.rb
3
- #
4
- # Test case for stat related methods of win32-file. You should use
5
- # the 'rake test' task to run these tests.
6
- #####################################################################
7
- require 'rubygems'
8
- gem 'test-unit'
9
-
10
- require 'test/unit'
11
- require 'win32/file/stat'
12
-
13
- class TC_Win32_File_Stat < Test::Unit::TestCase
14
- include Windows::File
15
- include Windows::Process
16
- include Windows::Volume
17
- extend Windows::Volume
18
-
19
- def self.startup
20
- Dir.chdir(File.expand_path(File.dirname(__FILE__)))
21
-
22
- 'A'.upto('Z'){ |volume|
23
- volume += ":\\"
24
- case GetDriveType(volume)
25
- when DRIVE_REMOVABLE, DRIVE_CDROM, DRIVE_RAMDISK
26
- @@block_dev = volume
27
- break
28
- end
29
- }
30
-
31
- @@txt_file = 'test_file.txt'
32
- @@exe_file = 'test_file.exe'
33
- @@sys_file = 'C:/pagefile.sys'
34
-
35
- File.open(@@txt_file, "w"){ |fh| fh.print "This is a test\nHello" }
36
- File.open(@@exe_file, "wb"){ |fh| fh.print "This is a test" }
37
- end
38
-
39
- def setup
40
- @dir = Dir.pwd
41
- @stat = File::Stat.new(@@txt_file)
42
- @attr = GetFileAttributes(@@txt_file)
43
- end
44
-
45
- def test_version
46
- assert_equal('1.3.6', File::Stat::VERSION)
47
- end
48
-
49
- # One or more tests will fail if the archive attribute on @@text_file
50
- # is not set.
51
- def test_archive
52
- assert_respond_to(@stat, :archive?)
53
- assert_nothing_raised{ @stat.archive? }
54
- assert(@stat.archive?, '=> May fail - ignore')
55
- end
56
-
57
- def test_atime
58
- assert_respond_to(@stat, :atime)
59
- assert_kind_of(Time, @stat.atime)
60
- end
61
-
62
- def test_blksize
63
- assert_respond_to(@stat, :blksize)
64
- assert_equal(4096, @stat.blksize)
65
- assert_equal(4096, File::Stat.new("C:\\").blksize)
66
- end
67
-
68
- # The block dev test error out if there's no media in it.
69
- def test_blockdev
70
- assert_respond_to(@stat, :blockdev?)
71
- assert_false(@stat.blockdev?)
72
- assert_false(File::Stat.new('NUL').blockdev?)
73
-
74
- begin
75
- assert_true(File::Stat.new(@@block_dev).blockdev?)
76
- rescue StandardError, SystemCallError
77
- omit("Skipping because drive is empty or not found")
78
- end
79
- end
80
-
81
- def test_blocks
82
- assert_respond_to(@stat, :blocks)
83
- assert_equal(1, @stat.blocks)
84
- end
85
-
86
- def test_chardev
87
- assert_respond_to(@stat, :chardev?)
88
- assert_nothing_raised{ File::Stat.new("NUL").chardev? }
89
- assert_equal(true, File::Stat.new("NUL").chardev?)
90
- assert_equal(false, File::Stat.new("C:\\").chardev?)
91
- end
92
-
93
- def test_comparison
94
- assert_respond_to(@stat, :<=>)
95
- assert_nothing_raised{ @stat <=> File::Stat.new(@@exe_file) }
96
- end
97
-
98
- def test_compressed
99
- assert_respond_to(@stat, :compressed?)
100
- assert_nothing_raised{ @stat.compressed? }
101
- assert_equal(false, @stat.compressed?)
102
- end
103
-
104
- def test_ctime
105
- assert_respond_to(@stat, :ctime)
106
- assert_kind_of(Time, @stat.ctime)
107
- end
108
-
109
- # Assumes you've installed on C: drive.
110
- def test_dev
111
- assert_respond_to(@stat, :dev)
112
- assert_equal('C:', @stat.dev)
113
- end
114
-
115
- def test_dev_major
116
- assert_respond_to(@stat, :dev_major)
117
- assert_nil(@stat.dev_major)
118
- end
119
-
120
- def test_dev_minor
121
- assert_respond_to(@stat, :dev_minor)
122
- assert_nil(@stat.dev_minor)
123
- end
124
-
125
- def test_directory
126
- assert_respond_to(@stat, :directory?)
127
- assert_equal(false, @stat.directory?)
128
- assert_equal(true, File::Stat.new("C:\\").directory?)
129
- end
130
-
131
- def test_executable
132
- assert_respond_to(@stat, :executable?)
133
- assert_equal(false, @stat.executable?)
134
- assert_equal(true, File::Stat.new(@@exe_file).executable?)
135
- end
136
-
137
- def test_executable_real
138
- assert_respond_to(@stat, :executable_real?)
139
- assert_equal(false, @stat.executable_real?)
140
- assert_equal(true, File::Stat.new(@@exe_file).executable_real?)
141
- end
142
-
143
- def test_file
144
- assert_respond_to(@stat, :file?)
145
- assert_equal(true, @stat.file?)
146
- assert_equal(true, File::Stat.new(@@exe_file).file?)
147
- assert_equal(true, File::Stat.new(Dir.pwd).file?)
148
- assert_equal(false, File::Stat.new('NUL').file?)
149
- end
150
-
151
- def test_ftype
152
- assert_respond_to(@stat, :ftype)
153
- assert_equal('file', @stat.ftype)
154
- assert_equal('characterSpecial', File::Stat.new('NUL').ftype)
155
- assert_equal('directory', File::Stat.new(Dir.pwd).ftype)
156
- end
157
-
158
- def encrypted
159
- assert_respond_to(@stat, :encrypted?)
160
- assert_nothing_raised{ @stat.encrypted? }
161
- end
162
-
163
- def test_gid
164
- assert_respond_to(@stat, :gid)
165
- assert_equal(0, @stat.gid)
166
- end
167
-
168
- def test_grpowned
169
- assert_respond_to(@stat, :grpowned?)
170
- end
171
-
172
- def test_hidden
173
- assert_respond_to(@stat, :hidden?)
174
- assert_nothing_raised{ @stat.hidden? }
175
- assert_equal(false, @stat.hidden?)
176
- end
177
-
178
- def test_indexed
179
- assert_respond_to(@stat, :indexed?)
180
- assert_respond_to(@stat, :content_indexed?) # alias
181
- assert_nothing_raised{ @stat.indexed? }
182
- assert(@stat.indexed?)
183
- end
184
-
185
- def test_ino
186
- assert_respond_to(@stat, :ino)
187
- assert_equal(0, @stat.ino)
188
- end
189
-
190
- def test_inspect
191
- assert_respond_to(@stat, :inspect)
192
- end
193
-
194
- def test_mode
195
- assert_respond_to(@stat, :mode)
196
- assert_equal(33188, File::Stat.new(@@txt_file).mode)
197
- assert_equal(33261, File::Stat.new(@@exe_file).mode)
198
- assert_equal(16877, File::Stat.new(@dir).mode)
199
-
200
- SetFileAttributes(@@txt_file, 1) # Set to readonly.
201
- assert_equal(33060, File::Stat.new(@@txt_file).mode)
202
- end
203
-
204
- def test_mtime
205
- assert_respond_to(@stat, :mtime)
206
- assert_kind_of(Time, @stat.mtime)
207
- end
208
-
209
- def test_nlink
210
- assert_respond_to(@stat, :nlink)
211
- assert_equal(1, @stat.nlink)
212
- end
213
-
214
- def test_normal
215
- assert_respond_to(@stat, :normal?)
216
- assert_nothing_raised{ @stat.normal? }
217
- assert_equal(false, @stat.normal?)
218
- end
219
-
220
- def test_offline
221
- assert_respond_to(@stat, :offline?)
222
- assert_nothing_raised{ @stat.offline? }
223
- assert_equal(false, @stat.offline?)
224
- end
225
-
226
- def test_pipe
227
- assert_respond_to(@stat, :pipe?)
228
- assert_equal(false, @stat.pipe?)
229
- end
230
-
231
- def test_readable
232
- assert_respond_to(@stat, :readable?)
233
- assert_equal(true, @stat.readable?)
234
- end
235
-
236
- def test_readable_real
237
- assert_respond_to(@stat, :readable_real?)
238
- assert_equal(true, @stat.readable_real?)
239
- end
240
-
241
- def test_readonly
242
- assert_respond_to(@stat, :readonly?)
243
- assert_nothing_raised{ @stat.readonly? }
244
- assert_equal(false, @stat.readonly?)
245
- end
246
-
247
- def test_reparse_point
248
- assert_respond_to(@stat, :reparse_point?)
249
- assert_nothing_raised{ @stat.reparse_point? }
250
- assert_equal(false, @stat.reparse_point?)
251
- end
252
-
253
- # Assumes you've installed on C: drive.
254
- def test_rdev
255
- msg = "ignore failure if Ruby is not installed on C: drive"
256
- assert_respond_to(@stat, :rdev)
257
- assert_equal(2, @stat.rdev, msg)
258
- end
259
-
260
- def test_setgid
261
- assert_respond_to(@stat, :setgid?)
262
- assert_equal(false, @stat.setgid?)
263
- end
264
-
265
- def test_setuid
266
- assert_respond_to(@stat, :setuid?)
267
- assert_equal(false, @stat.setuid?)
268
- end
269
-
270
- def test_size
271
- assert_respond_to(@stat, :size)
272
- assert_equal(21, @stat.size)
273
- end
274
-
275
- def test_size_system_file
276
- omit_if(windows_64?, 'skipping system file test on 64-bit OS')
277
- assert_nothing_raised{ File::Stat.new(@@sys_file).size }
278
- end
279
-
280
- def test_size_bool
281
- assert_respond_to(@stat, :size?)
282
- assert_equal(21, @stat.size?)
283
- end
284
-
285
- def test_socket
286
- assert_respond_to(@stat, :socket?)
287
- assert_equal(false, @stat.socket?)
288
- end
289
-
290
- def test_sparse
291
- assert_respond_to(@stat, :sparse?)
292
- assert_nothing_raised{ @stat.sparse? }
293
- assert_equal(false, @stat.sparse?)
294
- end
295
-
296
- def test_sticky
297
- assert_respond_to(@stat, :sticky?)
298
- assert_equal(false, @stat.sticky?)
299
- end
300
-
301
- def test_symlink
302
- assert_respond_to(@stat, :symlink?)
303
- assert_equal(false, @stat.symlink?)
304
- end
305
-
306
- def test_system
307
- assert_respond_to(@stat, :system?)
308
- assert_nothing_raised{ @stat.system? }
309
- assert_equal(false, @stat.system?)
310
- end
311
-
312
- def test_temporary
313
- assert_respond_to(@stat, :temporary?)
314
- assert_nothing_raised{ @stat.temporary? }
315
- assert_equal(false, @stat.temporary?)
316
- end
317
-
318
- def test_uid
319
- assert_respond_to(@stat, :uid)
320
- assert_equal(0, @stat.uid)
321
- end
322
-
323
- def test_writable
324
- assert_respond_to(@stat, :writable?)
325
- assert_equal(true, @stat.writable?)
326
- end
327
-
328
- def test_writable_real
329
- assert_respond_to(@stat, :writable_real?)
330
- assert_equal(true, @stat.writable_real?)
331
- end
332
-
333
- def test_zero
334
- assert_respond_to(@stat, :zero?)
335
- assert_equal(false, @stat.zero?)
336
- end
337
-
338
- def teardown
339
- SetFileAttributes(@@txt_file, @attr) # Set file back to normal
340
- @dir = nil
341
- @stat = nil
342
- @attr = nil
343
- end
344
-
345
- def self.shutdown
346
- File.delete(@@txt_file) if File.exists?(@@txt_file)
347
- File.delete(@@exe_file) if File.exists?(@@exe_file)
348
-
349
- @@block_dev = nil
350
- @@txt_file = nil
351
- @@exe_file = nil
352
- @@sys_file = nil
353
- end
354
- end
1
+ #####################################################################
2
+ # test_file_stat.rb
3
+ #
4
+ # Test case for stat related methods of win32-file. You should use
5
+ # the 'rake test' task to run these tests.
6
+ #####################################################################
7
+ require 'etc'
8
+ require 'ffi'
9
+ require 'test-unit'
10
+ require 'win32/file/stat'
11
+ require 'win32/security'
12
+
13
+ class TC_Win32_File_Stat < Test::Unit::TestCase
14
+ extend FFI::Library
15
+ ffi_lib :kernel32
16
+
17
+ attach_function :GetDriveType, :GetDriveTypeA, [:string], :ulong
18
+ attach_function :GetFileAttributes, :GetFileAttributesA, [:string], :ulong
19
+ attach_function :SetFileAttributes, :SetFileAttributesA, [:string, :ulong], :bool
20
+
21
+ DRIVE_REMOVABLE = 2
22
+ DRIVE_CDROM = 5
23
+ DRIVE_RAMDISK = 6
24
+
25
+ def self.startup
26
+ @@block_dev = nil
27
+
28
+ 'A'.upto('Z'){ |volume|
29
+ volume += ":\\"
30
+ case GetDriveType(volume)
31
+ when DRIVE_REMOVABLE, DRIVE_CDROM, DRIVE_RAMDISK
32
+ @@block_dev = volume
33
+ break
34
+ end
35
+ }
36
+
37
+ @@txt_file = File.join(File.expand_path(File.dirname(__FILE__)), 'test_file.txt')
38
+ @@exe_file = File.join(File.expand_path(File.dirname(__FILE__)), 'test_file.exe')
39
+ @@sys_file = 'C:/pagefile.sys'
40
+ @@elevated = Win32::Security.elevated_security?
41
+ @@jruby = RUBY_PLATFORM == 'java'
42
+
43
+ File.open(@@txt_file, "w"){ |fh| fh.print "This is a test\nHello" }
44
+ File.open(@@exe_file, "wb"){ |fh| fh.print "This is a test" }
45
+ end
46
+
47
+ def setup
48
+ @dir = Dir.pwd
49
+ @stat = File::Stat.new(@@txt_file)
50
+ @temp = 'win32_file_stat.tmp'
51
+ File.open(@temp, 'w'){}
52
+ @attr = GetFileAttributes(@@txt_file)
53
+ end
54
+
55
+ test "version is set to expected value" do
56
+ assert_equal('1.4.0', File::Stat::WIN32_FILE_STAT_VERSION)
57
+ end
58
+
59
+ test "constructor does not modify argument" do
60
+ expected = File.join(File.expand_path(File.dirname(__FILE__)), 'test_file.txt')
61
+ File::Stat.new(@@txt_file)
62
+ assert_equal(expected, @@txt_file)
63
+ end
64
+
65
+ test "archive? method basic functionality" do
66
+ assert_respond_to(@stat, :archive?)
67
+ assert_nothing_raised{ @stat.archive? }
68
+ end
69
+
70
+ test "archive? method returns a boolean value" do
71
+ assert_boolean(@stat.archive?)
72
+ end
73
+
74
+ test "atime method basic functionality" do
75
+ assert_respond_to(@stat, :atime)
76
+ assert_nothing_raised{ @stat.atime }
77
+ end
78
+
79
+ test "atime method returns expected value" do
80
+ assert_kind_of(Time, @stat.atime)
81
+ assert_true(@stat.atime.to_i > 0)
82
+ end
83
+
84
+ test "mtime method basic functionality" do
85
+ assert_respond_to(@stat, :mtime)
86
+ assert_nothing_raised{ @stat.mtime }
87
+ end
88
+
89
+ test "mtime method returns expected value" do
90
+ assert_kind_of(Time, @stat.mtime)
91
+ assert_true(@stat.mtime.to_i > 0)
92
+ end
93
+
94
+ test "ctime method basic functionality" do
95
+ assert_respond_to(@stat, :ctime)
96
+ assert_nothing_raised{ @stat.ctime }
97
+ end
98
+
99
+ test "ctime method returns expected value" do
100
+ assert_kind_of(Time, @stat.ctime)
101
+ assert_true(@stat.ctime.to_i > 0)
102
+ end
103
+
104
+ test "blksize basic functionality" do
105
+ assert_respond_to(@stat, :blksize)
106
+ assert_kind_of(Fixnum, @stat.blksize)
107
+ end
108
+
109
+ test "blksize returns expected value" do
110
+ assert_equal(4096, @stat.blksize)
111
+ assert_equal(4096, File::Stat.new("C:\\").blksize)
112
+ end
113
+
114
+ test "blockdev? basic functionality" do
115
+ assert_respond_to(@stat, :blockdev?)
116
+ assert_boolean(@stat.blockdev?)
117
+ end
118
+
119
+ test "blockdev? returns the expected value for a non-block device" do
120
+ assert_false(@stat.blockdev?)
121
+ assert_false(File::Stat.new('NUL').blockdev?)
122
+ end
123
+
124
+ # In unusual situations this could fail.
125
+ test "blockdev? returns the expected value for a block device" do
126
+ omit_unless(@@block_dev)
127
+ assert_true(File::Stat.new(@@block_dev).blockdev?)
128
+ end
129
+
130
+ test "blocks basic functionality" do
131
+ assert_respond_to(@stat, :blocks)
132
+ assert_kind_of(Fixnum, @stat.blocks)
133
+ end
134
+
135
+ test "blocks method returns expected value" do
136
+ assert_equal(1, @stat.blocks)
137
+ end
138
+
139
+ test "chardev? custom method basic functionality" do
140
+ assert_respond_to(@stat, :chardev?)
141
+ assert_boolean(@stat.chardev?)
142
+ end
143
+
144
+ test "chardev? custom method returns expected value" do
145
+ assert_true(File::Stat.new("NUL").chardev?)
146
+ assert_false(File::Stat.new("C:\\").chardev?)
147
+ end
148
+
149
+ test "custom comparison method basic functionality" do
150
+ assert_respond_to(@stat, :<=>)
151
+ assert_nothing_raised{ @stat <=> File::Stat.new(@@exe_file) }
152
+ end
153
+
154
+ test "custom comparison method works as expected" do
155
+ assert_equal(0, @stat <=> @stat)
156
+ end
157
+
158
+ test "compressed? basic functionality" do
159
+ assert_respond_to(@stat, :compressed?)
160
+ assert_boolean(@stat.compressed?)
161
+ end
162
+
163
+ test "compressed? returns expected value" do
164
+ assert_false(@stat.compressed?)
165
+ end
166
+
167
+ test "dev custom method basic functionality" do
168
+ assert_respond_to(@stat, :rdev)
169
+ assert_kind_of(Fixnum, @stat.rdev)
170
+ end
171
+
172
+ test "dev custom method returns expected value" do
173
+ notify "May fail on JRuby" if @@jruby
174
+ assert_equal(2, File::Stat.new("C:\\").dev)
175
+ assert_equal(-1, File::Stat.new("NUL").dev)
176
+ end
177
+
178
+ test "dev custom method accepts an optional argument" do
179
+ assert_nothing_raised{ File::Stat.new("C:\\").dev(true) }
180
+ assert_kind_of(String, File::Stat.new("C:\\").dev(true))
181
+ end
182
+
183
+ test "dev custom method with optional argument returns expected value" do
184
+ notify "May fail on JRuby" if @@jruby
185
+ assert_equal("C:", File::Stat.new("C:\\").dev(true))
186
+ assert_nil(File::Stat.new("NUL").dev(true))
187
+ end
188
+
189
+ test "dev_major defined and always returns nil" do
190
+ omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
191
+ assert_respond_to(@stat, :dev_major)
192
+ assert_nil(@stat.dev_major)
193
+ end
194
+
195
+ test "dev_minor defined and always returns nil" do
196
+ omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
197
+ assert_respond_to(@stat, :dev_minor)
198
+ assert_nil(@stat.dev_minor)
199
+ end
200
+
201
+ test "directory? custom method basic functionality" do
202
+ assert_respond_to(@stat, :directory?)
203
+ assert_boolean(@stat.directory?)
204
+ end
205
+
206
+ test "directory? custom method returns expected value" do
207
+ assert_false(@stat.directory?)
208
+ assert_true(File::Stat.new("C:\\").directory?)
209
+ end
210
+
211
+ test "executable? custom method basic functionality" do
212
+ assert_respond_to(@stat, :executable?)
213
+ assert_boolean(@stat.executable?)
214
+ end
215
+
216
+ test "executable? custom method returns expected value" do
217
+ assert_false(@stat.executable?)
218
+ assert_true(File::Stat.new(@@exe_file).executable?)
219
+ end
220
+
221
+ test "executable_real? is an alias for executable?" do
222
+ assert_respond_to(@stat, :executable_real?)
223
+ assert_alias_method(@stat, :executable?, :executable_real?)
224
+ end
225
+
226
+ test "file? custom method basic functionality" do
227
+ assert_respond_to(@stat, :file?)
228
+ assert_boolean(@stat.file?)
229
+ end
230
+
231
+ test "file? custom method returns expected value" do
232
+ assert_true(@stat.file?)
233
+ assert_true(File::Stat.new(@@exe_file).file?)
234
+ assert_true(File::Stat.new(Dir.pwd).file?)
235
+ assert_false(File::Stat.new('NUL').file?)
236
+ end
237
+
238
+ test "ftype custom method basic functionality" do
239
+ assert_respond_to(@stat, :ftype)
240
+ assert_kind_of(String, @stat.ftype)
241
+ end
242
+
243
+ test "ftype custom method returns expected value" do
244
+ assert_equal('file', @stat.ftype)
245
+ assert_equal('characterSpecial', File::Stat.new('NUL').ftype)
246
+ assert_equal('directory', File::Stat.new(Dir.pwd).ftype)
247
+ end
248
+
249
+ test "encrypted? basic functionality" do
250
+ assert_respond_to(@stat, :encrypted?)
251
+ assert_boolean(@stat.encrypted?)
252
+ end
253
+
254
+ test "encrypted? returns the expected value" do
255
+ assert_false(@stat.encrypted?)
256
+ end
257
+
258
+ test "gid method basic functionality" do
259
+ assert_respond_to(@stat, :gid)
260
+ assert_nothing_raised{ @stat.gid }
261
+ assert_kind_of(Fixnum, @stat.gid)
262
+ end
263
+
264
+ test "gid returns a sane result" do
265
+ assert_true(@stat.gid >= 0 && @stat.gid <= 10000)
266
+ end
267
+
268
+ test "gid returns a string argument if true argument provided" do
269
+ assert_nothing_raised{ @stat.gid(true) }
270
+ assert_match("S-1-", @stat.gid(true))
271
+ end
272
+
273
+ test "grpowned? defined and always returns true" do
274
+ assert_respond_to(@stat, :grpowned?)
275
+ end
276
+
277
+ test "hidden? basic functionality" do
278
+ assert_respond_to(@stat, :hidden?)
279
+ assert_boolean(@stat.hidden?)
280
+ end
281
+
282
+ test "hidden? returns expected value" do
283
+ assert_false(@stat.hidden?)
284
+ end
285
+
286
+ test "indexed? basic functionality" do
287
+ assert_respond_to(@stat, :indexed?)
288
+ assert_boolean(@stat.indexed?)
289
+ end
290
+
291
+ test "indexed? returns expected value" do
292
+ assert_true(@stat.indexed?)
293
+ end
294
+
295
+ test "content_indexed? is an alias for indexed?" do
296
+ assert_respond_to(@stat, :content_indexed?)
297
+ assert_alias_method(@stat, :indexed?, :content_indexed?)
298
+ end
299
+
300
+ test "ino method basic functionality" do
301
+ assert_respond_to(@stat, :ino)
302
+ assert_nothing_raised{ @stat.ino }
303
+ assert_kind_of(Numeric, @stat.ino)
304
+ end
305
+
306
+ test "ino method returns a sane value" do
307
+ assert_true(@stat.ino > 1000)
308
+ end
309
+
310
+ test "ino method returns nil on a special device" do
311
+ assert_nil(File::Stat.new("NUL").ino)
312
+ end
313
+
314
+ test "inspect custom method basic functionality" do
315
+ assert_respond_to(@stat, :inspect)
316
+ end
317
+
318
+ test "inspect string contains expected values" do
319
+ assert_match('File::Stat', @stat.inspect)
320
+ assert_match('compressed', @stat.inspect)
321
+ assert_match('normal', @stat.inspect)
322
+ end
323
+
324
+ test "mode custom method basic functionality" do
325
+ assert_respond_to(@stat, :mode)
326
+ assert_kind_of(Fixnum, @stat.mode)
327
+ end
328
+
329
+ test "mode custom method returns the expected value" do
330
+ assert_equal(33188, File::Stat.new(@@txt_file).mode)
331
+ assert_equal(33261, File::Stat.new(@@exe_file).mode)
332
+ assert_equal(16877, File::Stat.new(@dir).mode)
333
+ end
334
+
335
+ test "mode custom method returns expected value for readonly file" do
336
+ SetFileAttributes(@@txt_file, 1) # Set to readonly.
337
+ assert_equal(33060, File::Stat.new(@@txt_file).mode)
338
+ end
339
+
340
+ test "nlink basic functionality" do
341
+ assert_respond_to(@stat, :nlink)
342
+ assert_kind_of(Fixnum, @stat.nlink)
343
+ end
344
+
345
+ test "nlink returns the expected value" do
346
+ assert_equal(1, @stat.nlink)
347
+ assert_equal(1, File::Stat.new(Dir.pwd).nlink)
348
+ assert_equal(1, File::Stat.new('NUL').nlink)
349
+ end
350
+
351
+ test "normal? basic functionality" do
352
+ assert_respond_to(@stat, :normal?)
353
+ assert_boolean(@stat.normal?)
354
+ end
355
+
356
+ test "normal? returns expected value" do
357
+ assert_false(@stat.normal?)
358
+ end
359
+
360
+ test "offline? method basic functionality" do
361
+ assert_respond_to(@stat, :offline?)
362
+ assert_boolean(@stat.offline?)
363
+ end
364
+
365
+ test "offline? method returns expected value" do
366
+ assert_false(@stat.offline?)
367
+ end
368
+
369
+ test "owned? method basic functionality" do
370
+ assert_respond_to(@stat, :owned?)
371
+ assert_boolean(@stat.owned?)
372
+ end
373
+
374
+ test "owned? returns the expected results" do
375
+ if @@elevated
376
+ assert_false(@stat.owned?)
377
+ else
378
+ assert_true(@stat.owned?)
379
+ end
380
+ assert_false(File::Stat.new(@@sys_file).owned?)
381
+ end
382
+
383
+ test "pipe? custom method basic functionality" do
384
+ assert_respond_to(@stat, :pipe?)
385
+ assert_boolean(@stat.pipe?)
386
+ end
387
+
388
+ test "pipe? custom method returns expected value" do
389
+ assert_false(@stat.pipe?)
390
+ end
391
+
392
+ test "socket? is an alias for pipe?" do
393
+ assert_respond_to(@stat, :socket?)
394
+ assert_alias_method(@stat, :socket?, :pipe?)
395
+ end
396
+
397
+ test "readable? basic functionality" do
398
+ assert_respond_to(@stat, :readable?)
399
+ assert_boolean(@stat.readable?)
400
+ end
401
+
402
+ test "readable? returns expected value" do
403
+ assert_true(@stat.readable?)
404
+ assert_true(File::Stat.new(Dir.pwd).readable?)
405
+ assert_false(File::Stat.new(@@sys_file).readable?)
406
+ end
407
+
408
+ test "readable_real? basic functionality" do
409
+ assert_respond_to(@stat, :readable_real?)
410
+ assert_boolean(@stat.readable_real?)
411
+ end
412
+
413
+ test "readable_real? returns expected value" do
414
+ assert_true(@stat.readable_real?)
415
+ end
416
+
417
+ test "readonly? basic functionality" do
418
+ assert_respond_to(@stat, :readonly?)
419
+ assert_boolean(@stat.readonly?)
420
+ end
421
+
422
+ test "readonly? returns the expected value" do
423
+ assert_false(@stat.readonly?)
424
+ SetFileAttributes(@@txt_file, 1)
425
+ assert_true(File::Stat.new(@@txt_file).readonly?)
426
+ end
427
+
428
+ test "read_only? is an alias for readonly?" do
429
+ assert_respond_to(@stat, :read_only?)
430
+ assert_alias_method(@stat, :readonly?, :read_only?)
431
+ end
432
+
433
+ test "reparse_point? basic functionality" do
434
+ assert_respond_to(@stat, :reparse_point?)
435
+ assert_boolean(@stat.reparse_point?)
436
+ end
437
+
438
+ test "reparse_point returns expected value" do
439
+ assert_false(@stat.reparse_point?)
440
+ end
441
+
442
+ test "rdev basic functionality" do
443
+ assert_respond_to(@stat, :rdev)
444
+ assert_nothing_raised{ @stat.rdev }
445
+ assert_kind_of(Numeric, @stat.rdev)
446
+ end
447
+
448
+ test "rdev returns a sane value" do
449
+ assert_true(File::Stat.new("C:\\Program Files").rdev > 1000)
450
+ end
451
+
452
+ test "rdev returns nil on special files" do
453
+ assert_equal(nil, File::Stat.new("NUL").rdev)
454
+ end
455
+
456
+ # Not sure how to test properly in a generic way, but works on my local network
457
+ test "rdev works on unc path" do
458
+ omit_unless(Etc.getlogin == "djberge" && File.exists?("//scipio/users"))
459
+ assert_true(File::Stat.new("//scipio/users").rdev > 1000)
460
+ end
461
+
462
+ test "rdev_major defined and always returns nil" do
463
+ omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
464
+ assert_respond_to(@stat, :rdev_major)
465
+ assert_nil(@stat.rdev_major)
466
+ end
467
+
468
+ test "rdev_minor defined and always returns nil" do
469
+ omit_if(@@jruby) # https://github.com/jnr/jnr-posix/issues/23
470
+ assert_respond_to(@stat, :rdev_minor)
471
+ assert_nil(@stat.rdev_minor)
472
+ end
473
+
474
+ test "setgid is set to false" do
475
+ assert_respond_to(@stat, :setgid?)
476
+ assert_false(@stat.setgid?)
477
+ end
478
+
479
+ test "setuid is set to false" do
480
+ assert_respond_to(@stat, :setuid?)
481
+ assert_false(@stat.setuid?)
482
+ end
483
+
484
+ test "size custom method basic functionality" do
485
+ assert_respond_to(@stat, :size)
486
+ assert_kind_of(Numeric, @stat.size)
487
+ end
488
+
489
+ test "size custom method returns expected value" do
490
+ assert_equal(21, @stat.size)
491
+ @stat = File::Stat.new(@temp)
492
+ assert_equal(0, @stat.size)
493
+ end
494
+
495
+ test "size custom method works on system files" do
496
+ assert_nothing_raised{ File::Stat.new(@@sys_file).size }
497
+ end
498
+
499
+ test "size? method basic functionality" do
500
+ assert_respond_to(@stat, :size?)
501
+ assert_kind_of(Numeric, @stat.size)
502
+ end
503
+
504
+ test "size? method returns integer if size greater than zero" do
505
+ assert_equal(21, @stat.size?)
506
+ end
507
+
508
+ test "size? method returns nil if size is zero" do
509
+ @stat = File::Stat.new(@temp)
510
+ assert_nil(@stat.size?)
511
+ end
512
+
513
+ test "sparse? basic fucntionality" do
514
+ assert_respond_to(@stat, :sparse?)
515
+ assert_boolean(@stat.sparse?)
516
+ end
517
+
518
+ test "sparse? returns expected value" do
519
+ assert_false(@stat.sparse?)
520
+ end
521
+
522
+ test "sticky is always set to false" do
523
+ assert_respond_to(@stat, :sticky?)
524
+ assert_false(@stat.sticky?)
525
+ end
526
+
527
+ test "symlink? basic functionality" do
528
+ assert_respond_to(@stat, :symlink?)
529
+ assert_boolean(@stat.symlink?)
530
+ end
531
+
532
+ test "symlink? returns expected value" do
533
+ assert_false(@stat.symlink?)
534
+ end
535
+
536
+ test "system? basic functionality" do
537
+ assert_respond_to(@stat, :system?)
538
+ assert_boolean(@stat.system?)
539
+ end
540
+
541
+ test "system? returns expected value" do
542
+ assert_false(@stat.system?)
543
+ end
544
+
545
+ test "temporary? basic functionality" do
546
+ assert_respond_to(@stat, :temporary?)
547
+ assert_boolean(@stat.temporary?)
548
+ end
549
+
550
+ test "temporary? returns expected value" do
551
+ assert_false(@stat.temporary?)
552
+ end
553
+
554
+ test "uid basic functionality" do
555
+ assert_respond_to(@stat, :uid)
556
+ assert_nothing_raised{ @stat.uid }
557
+ assert_kind_of(Fixnum, @stat.uid)
558
+ end
559
+
560
+ test "uid returns a sane result" do
561
+ assert_true(@stat.uid >= 0 && @stat.uid <= 10000)
562
+ end
563
+
564
+ test "uid returns a string argument if true argument provided" do
565
+ assert_nothing_raised{ @stat.uid(true) }
566
+ assert_match("S-1-", @stat.uid(true))
567
+ end
568
+
569
+ test "world_readable? basic functionality" do
570
+ assert_respond_to(@stat, :world_readable?)
571
+ assert_boolean(@stat.world_readable?)
572
+ end
573
+
574
+ # TODO: Find or create a file that returns true.
575
+ test "world_readable? returns expected result" do
576
+ assert_false(@stat.world_readable?)
577
+ assert_false(File::Stat.new("C:/").world_readable?)
578
+ end
579
+
580
+ test "world_writable? basic functionality" do
581
+ assert_respond_to(@stat, :world_writable?)
582
+ assert_boolean(@stat.world_writable?)
583
+ end
584
+
585
+ # TODO: Find or create a file that returns true.
586
+ test "world_writable? returns expected result" do
587
+ assert_false(@stat.world_writable?)
588
+ assert_false(File::Stat.new("C:/").world_writable?)
589
+ end
590
+
591
+ test "writable? basic functionality" do
592
+ assert_respond_to(@stat, :writable?)
593
+ assert_boolean(@stat.writable?)
594
+ end
595
+
596
+ test "writable? returns expected value" do
597
+ assert_true(@stat.writable?)
598
+ assert_true(File::Stat.new(Dir.pwd).writable?)
599
+ assert_false(File::Stat.new(@@sys_file).writable?)
600
+ end
601
+
602
+ test "writable_real? basic functionality" do
603
+ assert_respond_to(@stat, :writable_real?)
604
+ assert_boolean(@stat.writable_real?)
605
+ end
606
+
607
+ test "writable_real? returns expected value" do
608
+ assert_true(@stat.writable_real?)
609
+ end
610
+
611
+ test "zero? method basic functionality" do
612
+ assert_respond_to(@stat, :zero?)
613
+ assert_boolean(@stat.zero?)
614
+ end
615
+
616
+ test "zero? method returns expected value" do
617
+ assert_false(@stat.zero?)
618
+ @stat = File::Stat.new(@temp)
619
+ assert_true(@stat.zero?)
620
+ end
621
+
622
+ test "ffi functions are private" do
623
+ assert_not_respond_to(@stat, :CloseHandle)
624
+ assert_not_respond_to(File::Stat, :CloseHandle)
625
+ end
626
+
627
+ def teardown
628
+ SetFileAttributes(@@txt_file, @attr) # Set file back to normal
629
+ File.delete(@temp) if File.exists?(@temp)
630
+ @dir = nil
631
+ @stat = nil
632
+ @attr = nil
633
+ @temp = nil
634
+ end
635
+
636
+ def self.shutdown
637
+ File.delete(@@txt_file) if File.exists?(@@txt_file)
638
+ File.delete(@@exe_file) if File.exists?(@@exe_file)
639
+
640
+ @@block_dev = nil
641
+ @@txt_file = nil
642
+ @@exe_file = nil
643
+ @@sys_file = nil
644
+ @@elevated = nil
645
+ @@jruby = nil
646
+ end
647
+ end