win32-file-stat 1.3.6 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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