New Upstream Snapshot - ruby-sys-filesystem

Ready changes

Summary

Merged new upstream version: 1.4.3+git20220916.1.3797d6d (was: 1.4.3).

Resulting package

Built on 2023-01-05T18:15 (took 6m7s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots ruby-sys-filesystem

Lintian Result

Diff

diff --git a/.rubocop.yml b/.rubocop.yml
new file mode 100644
index 0000000..8287501
--- /dev/null
+++ b/.rubocop.yml
@@ -0,0 +1,70 @@
+require: rubocop-rspec
+
+RSpec/MultipleExpectations:
+  Max: 4
+RSpec/ContextWording:
+  Enabled: false
+RSpec/FilePath:
+  SpecSuffixOnly: true
+RSpec/InstanceVariable:
+  Enabled: false
+RSpec/MultipleMemoizedHelpers:
+  Max: 10
+RSpec/BeforeAfterAll:
+  Enabled: false
+
+AllCops:
+  NewCops: enable
+  Exclude:
+    - sys-filesystem.gemspec
+    - Rakefile
+    - Gemfile
+    - examples/*.rb
+Lint/AssignmentInCondition:
+  Enabled: false
+Lint/EmptyBlock:
+  Exclude:
+    - spec/*.rb
+Style/FrozenStringLiteralComment:
+  Enabled: false
+Style/MethodCallWithoutArgsParentheses:
+  Enabled: false
+Style/NumericLiterals:
+  Enabled: false
+Style/NumericPredicate:
+  Enabled: false
+Style/ClassAndModuleChildren:
+  Enabled: false
+Style/ConditionalAssignment:
+  Enabled: false
+Style/GuardClause:
+  Enabled: false
+Style/HashSyntax:
+  Enabled: false
+Style/IfUnlessModifier:
+  Enabled: false
+Layout/EmptyLineAfterGuardClause:
+  Enabled: false
+Layout/CaseIndentation:
+  IndentOneStep: true
+Layout/SpaceBeforeBlockBraces:
+  Enabled: false
+Metrics/AbcSize:
+  Enabled: false
+Metrics/BlockLength:
+  IgnoredMethods: ['describe', 'context']
+Metrics/BlockNesting:
+  Max: 4
+Metrics/ClassLength:
+  Enabled: false
+Metrics/MethodLength:
+  Enabled: false
+Metrics/CyclomaticComplexity:
+  Enabled: false
+Metrics/PerceivedComplexity:
+  Enabled: false
+Naming/AccessorMethodName:
+  Enabled: false
+Naming/FileName:
+  Exclude:
+    - 'lib/sys-filesystem.rb'
diff --git a/Rakefile b/Rakefile
index 233d36c..3a0d38b 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,6 +1,7 @@
 require 'rake'
 require 'rake/clean'
 require 'rspec/core/rake_task'
+require 'rubocop/rake_task'
 
 CLEAN.include('**/*.gem', '**/*.rbc', '**/*.rbx', '**/*.lock')
 
@@ -25,6 +26,18 @@ task :example do
   sh "ruby -Ilib -Ilib/unix -Ilib/windows examples/example_stat.rb"
 end
 
+RuboCop::RakeTask.new
+
+namespace :rubocop do
+  RuboCop::RakeTask.new(:unix) do |task|
+    task.patterns = ['lib/sys/unix/sys/**/*.rb', 'spec/*unix*']
+  end
+
+  RuboCop::RakeTask.new(:windows) do |task|
+    task.patterns = ['lib/sys/windows/sys/**/*.rb', 'spec/*windows*']
+  end
+end
+
 desc "Run the test suite"
 RSpec::Core::RakeTask.new(:spec)
 
diff --git a/checksums.yaml.gz.sig b/checksums.yaml.gz.sig
deleted file mode 100644
index e357a92..0000000
Binary files a/checksums.yaml.gz.sig and /dev/null differ
diff --git a/data.tar.gz.sig b/data.tar.gz.sig
deleted file mode 100644
index a7e3668..0000000
Binary files a/data.tar.gz.sig and /dev/null differ
diff --git a/debian/changelog b/debian/changelog
index 085acef..4303fa9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,9 +1,10 @@
-ruby-sys-filesystem (1.4.3-2) UNRELEASED; urgency=medium
+ruby-sys-filesystem (1.4.3+git20220916.1.3797d6d-1) UNRELEASED; urgency=medium
 
   * Set upstream metadata fields: Repository-Browse.
   * Update standards version to 4.6.2, no changes needed.
+  * New upstream snapshot.
 
- -- Debian Janitor <janitor@jelmer.uk>  Thu, 05 Jan 2023 16:12:45 -0000
+ -- Debian Janitor <janitor@jelmer.uk>  Thu, 05 Jan 2023 18:11:10 -0000
 
 ruby-sys-filesystem (1.4.3-1) unstable; urgency=medium
 
diff --git a/lib/sys-filesystem.rb b/lib/sys-filesystem.rb
index 9dc6f88..e302a4d 100644
--- a/lib/sys-filesystem.rb
+++ b/lib/sys-filesystem.rb
@@ -1 +1,3 @@
+# frozen_string_literal: true
+
 require_relative 'sys/filesystem'
diff --git a/lib/sys/filesystem.rb b/lib/sys/filesystem.rb
index ff9de1c..5b4bb2c 100644
--- a/lib/sys/filesystem.rb
+++ b/lib/sys/filesystem.rb
@@ -1,9 +1,4 @@
-module Sys
-  class Filesystem
-    # The version of the sys-filesystem library
-    VERSION = '1.4.3'.freeze
-  end
-end
+# frozen_string_literal: true
 
 require 'rbconfig'
 
@@ -13,10 +8,18 @@ else
   require_relative 'unix/sys/filesystem'
 end
 
-# Methods universal to all platforms
+# Methods and properties universal to all platforms
 
+# The Sys module serves as a namespace only.
 module Sys
+  # The Filesystem class serves as an abstract base class. Its methods
+  # return objects of other types. Do not instantiate.
   class Filesystem
+    # The version of the sys-filesystem library
+    VERSION = '1.4.3'
+
+    # Stat objects are returned by the Sys::Filesystem.stat method. Here
+    # we're adding universal methods.
     class Stat
       # Returns true if the filesystem is case sensitive for the current path.
       # Typically this will be any path on MS Windows or Macs using HFS.
@@ -26,14 +29,12 @@ module Sys
       # general rule, I do not recommend using this method for a root path.
       #
       def case_insensitive?
-        if path !~ /\w+/
-          if RbConfig::CONFIG['host_os'] =~ /darwin|mac|windows|mswin|mingw/i
-            true # Assumes HFS
-          else
-            false
-          end
-        else
+        if path =~ /\w+/
           File.identical?(path, path.swapcase)
+        elsif RbConfig::CONFIG['host_os'] =~ /darwin|mac|windows|mswin|mingw/i
+          true # Assumes HFS/APFS on Mac
+        else
+          false
         end
       end
 
@@ -46,8 +47,8 @@ module Sys
   end
 end
 
-# Some convenient methods for converting bytes to kb, mb, and gb.
-#
+# Reopen the Numeric class and add some convenient methods
+# for converting bytes to kb, mb, and gb.
 class Numeric
   # call-seq:
   #  <tt>num</tt>.to_kb
diff --git a/lib/sys/unix/sys/filesystem.rb b/lib/sys/unix/sys/filesystem.rb
index 4045a07..a47144f 100644
--- a/lib/sys/unix/sys/filesystem.rb
+++ b/lib/sys/unix/sys/filesystem.rb
@@ -224,7 +224,7 @@ module Sys
       fs = Statvfs.new
 
       if statvfs(path, fs) < 0
-        raise Error, 'statvfs() function failed: ' + strerror(FFI.errno)
+        raise Error, "statvfs() function failed: #{strerror(FFI.errno)}"
       end
 
       obj = Sys::Filesystem::Stat.new
@@ -275,7 +275,7 @@ module Sys
         num = getmntinfo(buf, 2)
 
         if num == 0
-          raise Error, 'getmntinfo() function failed: ' + strerror(FFI.errno)
+          raise Error, "getmntinfo() function failed: #{strerror(FFI.errno)}"
         end
 
         ptr = buf.get_pointer(0)
@@ -419,7 +419,7 @@ module Sys
     #
     def self.mount(source, target, fstype = 'ext2', flags = 0, data = nil)
       if mount_c(source, target, fstype, flags, data) != 0
-        raise Error, 'mount() function failed: ' + strerror(FFI.errno)
+        raise Error, "mount() function failed: #{strerror(FFI.errno)}"
       end
 
       self
diff --git a/lib/sys/unix/sys/filesystem/constants.rb b/lib/sys/unix/sys/filesystem/constants.rb
index 6536e26..1f88e77 100644
--- a/lib/sys/unix/sys/filesystem/constants.rb
+++ b/lib/sys/unix/sys/filesystem/constants.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 module Sys
   class Filesystem
     module Constants
diff --git a/lib/sys/unix/sys/filesystem/functions.rb b/lib/sys/unix/sys/filesystem/functions.rb
index e2f9e7e..a3db52a 100644
--- a/lib/sys/unix/sys/filesystem/functions.rb
+++ b/lib/sys/unix/sys/filesystem/functions.rb
@@ -1,7 +1,10 @@
+# frozen_string_literal: true
+
 require 'ffi'
 
 module Sys
   class Filesystem
+    # A scoped module for internal FFI functions to be used by the main code.
     module Functions
       extend FFI::Library
 
@@ -9,18 +12,21 @@ module Sys
 
       def self.linux64?
         if RUBY_PLATFORM == 'java'
-          ENV_JAVA['sun.arch.data.model'].to_i == 64
+          RbConfig::CONFIG['host_os'] =~ /linux/i &&
+            ENV_JAVA['sun.arch.data.model'].to_i == 64
         else
           RbConfig::CONFIG['host_os'] =~ /linux/i &&
             (RbConfig::CONFIG['arch'] =~ /64/ || RbConfig::CONFIG['DEFS'] =~ /64/)
         end
       end
 
+      def self.solaris?
+        RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
+      end
+
       private_class_method :linux64?
 
-      if RbConfig::CONFIG['host_os'] =~ /sunos|solaris/i
-        attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
-      elsif linux64?
+      if linux64? || solaris?
         attach_function(:statvfs, :statvfs64, %i[string pointer], :int)
       else
         attach_function(:statvfs, %i[string pointer], :int)
diff --git a/lib/sys/unix/sys/filesystem/structs.rb b/lib/sys/unix/sys/filesystem/structs.rb
index bc39cd3..772a635 100644
--- a/lib/sys/unix/sys/filesystem/structs.rb
+++ b/lib/sys/unix/sys/filesystem/structs.rb
@@ -1,11 +1,14 @@
+# frozen_string_literal: true
+
 require 'ffi'
 require 'rbconfig'
 
 module Sys
   class Filesystem
     module Structs
+      # The Statfs struct is a subclass of FFI::Struct that corresponds to a struct statfs.
       class Statfs < FFI::Struct
-
+        # Private method that will determine the layout of the struct on Linux.
         def self.linux64?
           if RUBY_PLATFORM == 'java'
             ENV_JAVA['sun.arch.data.model'].to_i == 64
@@ -20,87 +23,88 @@ module Sys
         # FreeBSD 12.0 MNAMELEN from 88 => 1024.
         MNAMELEN =
           if RbConfig::CONFIG['host_os'] =~ /freebsd(.*)/i
-            $1.to_f < 12.0 ? 88 : 1024
+            Regexp.last_match(1).to_f < 12.0 ? 88 : 1024
           else
             88
           end
 
-        if RbConfig::CONFIG['host_os'] =~ /bsd/i
-          layout(
-            :f_version, :uint32,
-            :f_type, :uint32,
-            :f_flags, :uint64,
-            :f_bsize, :uint64,
-            :f_iosize, :int64,
-            :f_blocks, :uint64,
-            :f_bfree, :uint64,
-            :f_bavail, :int64,
-            :f_files, :uint64,
-            :f_ffree, :uint64,
-            :f_syncwrites, :uint64,
-            :f_asyncwrites, :uint64,
-            :f_syncreads, :uint64,
-            :f_asyncreads, :uint64,
-            :f_spare, [:uint64, 10],
-            :f_namemax, :uint32,
-            :f_owner, :int32,
-            :f_fsid,  [:int32, 2],
-            :f_charspare, [:char, 80],
-            :f_fstypename, [:char, 16],
-            :f_mntfromname, [:char, MNAMELEN],
-            :f_mntonname, [:char, MNAMELEN]
-          )
-        elsif RbConfig::CONFIG['host_os'] =~ /linux/i
-          if linux64?
+        case RbConfig::CONFIG['host_os']
+          when /bsd/i
             layout(
-              :f_type, :ulong,
-              :f_bsize, :ulong,
+              :f_version, :uint32,
+              :f_type, :uint32,
+              :f_flags, :uint64,
+              :f_bsize, :uint64,
+              :f_iosize, :int64,
               :f_blocks, :uint64,
               :f_bfree, :uint64,
-              :f_bavail, :uint64,
+              :f_bavail, :int64,
               :f_files, :uint64,
               :f_ffree, :uint64,
-              :f_fsid, [:int, 2],
-              :f_namelen, :ulong,
-              :f_frsize, :ulong,
-              :f_flags, :ulong,
-              :f_spare, [:ulong, 4]
+              :f_syncwrites, :uint64,
+              :f_asyncwrites, :uint64,
+              :f_syncreads, :uint64,
+              :f_asyncreads, :uint64,
+              :f_spare, [:uint64, 10],
+              :f_namemax, :uint32,
+              :f_owner, :int32,
+              :f_fsid,  [:int32, 2],
+              :f_charspare, [:char, 80],
+              :f_fstypename, [:char, 16],
+              :f_mntfromname, [:char, MNAMELEN],
+              :f_mntonname, [:char, MNAMELEN]
             )
+          when /linux/i
+            if linux64?
+              layout(
+                :f_type, :ulong,
+                :f_bsize, :ulong,
+                :f_blocks, :uint64,
+                :f_bfree, :uint64,
+                :f_bavail, :uint64,
+                :f_files, :uint64,
+                :f_ffree, :uint64,
+                :f_fsid, [:int, 2],
+                :f_namelen, :ulong,
+                :f_frsize, :ulong,
+                :f_flags, :ulong,
+                :f_spare, [:ulong, 4]
+              )
+            else
+              layout(
+                :f_type, :ulong,
+                :f_bsize, :ulong,
+                :f_blocks, :uint32,
+                :f_bfree, :uint32,
+                :f_bavail, :uint32,
+                :f_files, :uint32,
+                :f_ffree, :uint32,
+                :f_fsid, [:int, 2],
+                :f_namelen, :ulong,
+                :f_frsize, :ulong,
+                :f_flags, :ulong,
+                :f_spare, [:ulong, 4]
+              )
+            end
           else
             layout(
-              :f_type, :ulong,
-              :f_bsize, :ulong,
-              :f_blocks, :uint32,
-              :f_bfree, :uint32,
-              :f_bavail, :uint32,
-              :f_files, :uint32,
-              :f_ffree, :uint32,
-              :f_fsid, [:int, 2],
-              :f_namelen, :ulong,
-              :f_frsize, :ulong,
-              :f_flags, :ulong,
-              :f_spare, [:ulong, 4]
+              :f_bsize, :uint32,
+              :f_iosize, :int32,
+              :f_blocks, :uint64,
+              :f_bfree, :uint64,
+              :f_bavail, :uint64,
+              :f_files, :uint64,
+              :f_ffree, :uint64,
+              :f_fsid, [:int32, 2],
+              :f_owner, :int32,
+              :f_type, :uint32,
+              :f_flags, :uint32,
+              :f_fssubtype, :uint32,
+              :f_fstypename, [:char, 16],
+              :f_mntonname, [:char, 1024],
+              :f_mntfromname, [:char, 1024],
+              :f_reserved, [:uint32, 8]
             )
-          end
-        else
-          layout(
-            :f_bsize, :uint32,
-            :f_iosize, :int32,
-            :f_blocks, :uint64,
-            :f_bfree, :uint64,
-            :f_bavail, :uint64,
-            :f_files, :uint64,
-            :f_ffree, :uint64,
-            :f_fsid, [:int32, 2],
-            :f_owner, :int32,
-            :f_type, :uint32,
-            :f_flags, :uint32,
-            :f_fssubtype, :uint32,
-            :f_fstypename, [:char, 16],
-            :f_mntonname, [:char, 1024],
-            :f_mntfromname, [:char, 1024],
-            :f_reserved, [:uint32, 8]
-          )
         end
       end
 
diff --git a/lib/sys/windows/sys/filesystem.rb b/lib/sys/windows/sys/filesystem.rb
index 9199a55..3d4a0ec 100644
--- a/lib/sys/windows/sys/filesystem.rb
+++ b/lib/sys/windows/sys/filesystem.rb
@@ -9,7 +9,6 @@ require 'time'
 
 # The Sys module serves as a namespace only.
 module Sys
-
   # The Filesystem class encapsulates information about your filesystem.
   class Filesystem
     include Sys::Filesystem::Constants
@@ -20,6 +19,7 @@ module Sys
 
     private_class_method :new
 
+    # Mount objects are returned by the Sys::Filesystem.mounts method.
     class Mount
       # The name of the volume. This is the device mapping.
       attr_reader :name
@@ -50,6 +50,7 @@ module Sys
       alias freq frequency
     end
 
+    # Stat objects are returned by the Sys::Filesystem.stat method.
     class Stat
       # The path of the file system.
       attr_reader :path
@@ -160,6 +161,8 @@ module Sys
     #--
     # I couldn't really find a good reason to use the wide functions for this
     # method. If you have one, patches welcome.
+    #--
+    # rubocop:disable Metrics/BlockLength
     #
     def self.mounts
       # First call, get needed buffer size
@@ -196,14 +199,14 @@ module Sys
         filesystem_flags     = FFI::MemoryPointer.new(:ulong)
 
         bool = GetVolumeInformationA(
-           drive,
-           volume,
-           volume.size,
-           volume_serial_number,
-           max_component_length,
-           filesystem_flags,
-           fsname,
-           fsname.size
+          drive,
+          volume,
+          volume.size,
+          volume_serial_number,
+          max_component_length,
+          filesystem_flags,
+          fsname,
+          fsname.size
         )
 
         # Skip unmounted floppies or cd-roms, or inaccessible drives
@@ -237,6 +240,7 @@ module Sys
 
       mounts # Nil if the block form was used.
     end
+    # rubocop:enable Metrics/BlockLength
 
     # Returns the mount point for the given +file+. For MS Windows this
     # means the root of the path.
@@ -250,8 +254,6 @@ module Sys
 
       if PathStripToRootW(wfile)
         wfile.read_string(wfile.size).split("\000\000").first.tr(0.chr, '')
-      else
-        nil
       end
     end
 
diff --git a/lib/sys/windows/sys/filesystem/functions.rb b/lib/sys/windows/sys/filesystem/functions.rb
index 654e2ad..c8db22a 100644
--- a/lib/sys/windows/sys/filesystem/functions.rb
+++ b/lib/sys/windows/sys/filesystem/functions.rb
@@ -2,6 +2,7 @@ require 'ffi'
 
 module Sys
   class Filesystem
+    # Wrapper module for Windows related FFI functions.
     module Functions
       extend FFI::Library
       ffi_lib :kernel32
diff --git a/lib/sys/windows/sys/filesystem/helper.rb b/lib/sys/windows/sys/filesystem/helper.rb
index 6dd492a..0b5685a 100644
--- a/lib/sys/windows/sys/filesystem/helper.rb
+++ b/lib/sys/windows/sys/filesystem/helper.rb
@@ -1,6 +1,9 @@
+# Reopen core Ruby classes here and add some custom methods.
 class String
   # Convenience method for converting strings to UTF-16LE for wide character
   # functions that require it.
+  #--
+  # TODO: Use a refinement.
   def wincode
     (tr(File::SEPARATOR, File::ALT_SEPARATOR) + 0.chr).encode('UTF-16LE')
   end
diff --git a/metadata.gz.sig b/metadata.gz.sig
deleted file mode 100644
index c764989..0000000
--- a/metadata.gz.sig
+++ /dev/null
@@ -1 +0,0 @@
-�)Q�ge������@������F`FT"��1�O&���j$�<�O/>�D�n�3�`s��8�,���,�$"p%���sG��?�F�~i�K0�Ю#�b��^�>�0�",Y�v "L��P�lW��l�2�]О+Kɦ��M"�o���ݞ�>��D�M��*��*ݷu����4�:Z��tv&GiɊD�?Ệε\���QI�8��]Do89��l/���7��Q���q�$��l@�ᗆ��x��[H[�y�HWя���-�;������)1}��+�PpxMwM���Y2�#�����'y;��μ���>��`�k�����c[��Zo�}+�\V_�X�=�R���~�O���K������gN�c�Z��O�
\ No newline at end of file
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index d337bf3..6e3a866 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -1,6 +1,10 @@
+# frozen_string_literal: true
+
 require 'rspec'
+require 'sys_filesystem_shared'
 
 RSpec.configure do |config|
+  config.include_context(Sys::Filesystem)
   config.filter_run_excluding(:windows) unless Gem.win_platform?
   config.filter_run_excluding(:unix) if Gem.win_platform?
 end
diff --git a/spec/sys_filesystem_shared.rb b/spec/sys_filesystem_shared.rb
new file mode 100644
index 0000000..78023e3
--- /dev/null
+++ b/spec/sys_filesystem_shared.rb
@@ -0,0 +1,14 @@
+# frozen_string_literal: true
+
+require 'sys-filesystem'
+
+RSpec.shared_examples Sys::Filesystem do
+  example 'version number is set to the expected value' do
+    expect(Sys::Filesystem::VERSION).to eq('1.4.3')
+    expect(Sys::Filesystem::VERSION).to be_frozen
+  end
+
+  example 'you cannot instantiate an instance' do
+    expect{ described_class.new }.to raise_error(NoMethodError)
+  end
+end
diff --git a/spec/sys_filesystem_unix_spec.rb b/spec/sys_filesystem_unix_spec.rb
index 43a9218..dbd844c 100644
--- a/spec/sys_filesystem_unix_spec.rb
+++ b/spec/sys_filesystem_unix_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 ####################################################################
 # sys_filesystem_unix_spec.rb
 #
@@ -16,381 +18,495 @@ RSpec.describe Sys::Filesystem, :unix => true do
   let(:root)    { '/' }
 
   before do
-    @stat  = Sys::Filesystem.stat(root)
+    @stat  = described_class.stat(root)
     @size  = 58720256
   end
 
-  example "version number is set to the expected value" do
-    expect(Sys::Filesystem::VERSION).to eq('1.4.3')
-    expect(Sys::Filesystem::VERSION).to be_frozen
-  end
-
-  example "you cannot instantiate an instance" do
-    expect{ described_class.new }.to raise_error(NoMethodError)
-  end
-
-  example "stat path works as expected" do
+  example 'stat path works as expected' do
     expect(@stat).to respond_to(:path)
     expect(@stat.path).to eq(root)
   end
 
-  example "stat block_size works as expected" do
+  example 'stat block_size works as expected' do
     expect(@stat).to respond_to(:block_size)
     expect(@stat.block_size).to be_kind_of(Numeric)
   end
 
-  example "stat fragment_size works as expected" do
+  example 'stat fragment_size works as expected' do
     expect(@stat).to respond_to(:fragment_size)
     expect(@stat.fragment_size).to be_kind_of(Numeric)
   end
 
-  example "stat fragment_size is a plausible value" do
+  example 'stat fragment_size is a plausible value' do
     expect(@stat.fragment_size).to be >= 512
     expect(@stat.fragment_size).to be <= 16384
   end
 
-  example "stat blocks works as expected" do
+  example 'stat blocks works as expected' do
     expect(@stat).to respond_to(:blocks)
     expect(@stat.blocks).to be_kind_of(Numeric)
   end
 
-  example "stat blocks_free works as expected" do
+  example 'stat blocks_free works as expected' do
     expect(@stat).to respond_to(:blocks_free)
     expect(@stat.blocks_free).to be_kind_of(Numeric)
   end
 
-  example "stat blocks_available works as expected" do
+  example 'stat blocks_available works as expected' do
     expect(@stat).to respond_to(:blocks_available)
     expect(@stat.blocks_available).to be_kind_of(Numeric)
   end
 
-  example "stat files works as expected" do
+  example 'stat files works as expected' do
     expect(@stat).to respond_to(:files)
     expect(@stat.files).to be_kind_of(Numeric)
   end
 
-  example "stat inodes is an alias for files" do
+  example 'stat inodes is an alias for files' do
     expect(@stat).to respond_to(:inodes)
     expect(@stat.method(:inodes)).to eq(@stat.method(:files))
   end
 
-  example "stat files tree works as expected" do
+  example 'stat files tree works as expected' do
     expect(@stat).to respond_to(:files_free)
     expect(@stat.files_free).to be_kind_of(Numeric)
   end
 
-  example "stat inodes_free is an alias for files_free" do
+  example 'stat inodes_free is an alias for files_free' do
     expect(@stat).to respond_to(:inodes_free)
     expect(@stat.method(:inodes_free)).to eq(@stat.method(:files_free))
   end
 
-  example "stat files_available works as expected" do
+  example 'stat files_available works as expected' do
     expect(@stat).to respond_to(:files_available)
     expect(@stat.files_available).to be_kind_of(Numeric)
   end
 
-  example "stat inodes_available is an alias for files_available" do
+  example 'stat inodes_available is an alias for files_available' do
     expect(@stat).to respond_to(:inodes_available)
     expect(@stat.method(:inodes_available)).to eq(@stat.method(:files_available))
   end
 
-  example "stat filesystem_id works as expected" do
+  example 'stat filesystem_id works as expected' do
     expect(@stat).to respond_to(:filesystem_id)
     expect(@stat.filesystem_id).to be_kind_of(Integer)
   end
 
-  example "stat flags works as expected" do
+  example 'stat flags works as expected' do
     expect(@stat).to respond_to(:flags)
     expect(@stat.flags).to be_kind_of(Numeric)
   end
 
-  example "stat name_max works as expected" do
+  example 'stat name_max works as expected' do
     expect(@stat).to respond_to(:name_max)
     expect(@stat.name_max).to be_kind_of(Numeric)
   end
 
-  example "stat base_type works as expected" do
-    skip "base_type test skipped except on Solaris" unless solaris
+  example 'stat base_type works as expected' do
+    skip 'base_type test skipped except on Solaris' unless solaris
 
     expect(@stat).to respond_to(:base_type)
     expect(@stat.base_type).to be_kind_of(String)
   end
 
-  example "stat constants are defined" do
+  example 'stat constants are defined' do
     expect(Sys::Filesystem::Stat::RDONLY).not_to be_nil
     expect(Sys::Filesystem::Stat::NOSUID).not_to be_nil
   end
 
-  example "stat constants for solaris are defined" do
-    skip "NOTRUNC test skipped except on Solaris" unless solaris
+  example 'stat constants for solaris are defined' do
+    skip 'NOTRUNC test skipped except on Solaris' unless solaris
     expect(Sys::Filesystem::Stat::NOTRUNC).not_to be_nil
   end
 
-  example "stat bytes_total works as expected" do
+  example 'stat bytes_total works as expected' do
     expect(@stat).to respond_to(:bytes_total)
     expect(@stat.bytes_total).to be_kind_of(Numeric)
   end
 
-  example "stat bytes_free works as expected" do
+  example 'stat bytes_free works as expected' do
     expect(@stat).to respond_to(:bytes_free)
     expect(@stat.bytes_free).to be_kind_of(Numeric)
     expect(@stat.blocks_free * @stat.fragment_size).to eq(@stat.bytes_free)
   end
 
-  example "stat bytes_available works as expected" do
+  example 'stat bytes_available works as expected' do
     expect(@stat).to respond_to(:bytes_available)
     expect(@stat.bytes_available).to be_kind_of(Numeric)
     expect(@stat.blocks_available * @stat.fragment_size).to eq(@stat.bytes_available)
   end
 
-  example "stat bytes works as expected" do
+  example 'stat bytes works as expected' do
     expect(@stat).to respond_to(:bytes_used)
     expect(@stat.bytes_used).to be_kind_of(Numeric)
   end
 
-  example "stat percent_used works as expected" do
+  example 'stat percent_used works as expected' do
     expect(@stat).to respond_to(:percent_used)
     expect(@stat.percent_used).to be_kind_of(Float)
   end
 
-  example "stat singleton method requires an argument" do
-    expect{ Sys::Filesystem.stat }.to raise_error(ArgumentError)
+  example 'stat singleton method requires an argument' do
+    expect{ described_class.stat }.to raise_error(ArgumentError)
   end
 
-  example "stat case_insensitive method works as expected" do
+  example 'stat case_insensitive method works as expected' do
     expected = darwin ? true : false
     expect(@stat.case_insensitive?).to eq(expected)
-    expect(Sys::Filesystem.stat(Dir.home).case_insensitive?).to eq(expected)
+    expect(described_class.stat(Dir.home).case_insensitive?).to eq(expected)
   end
 
-  example "stat case_sensitive method works as expected" do
+  example 'stat case_sensitive method works as expected' do
     expected = darwin ? false : true
     expect(@stat.case_sensitive?).to eq(expected)
-    expect(Sys::Filesystem.stat(Dir.home).case_sensitive?).to eq(expected)
+    expect(described_class.stat(Dir.home).case_sensitive?).to eq(expected)
   end
 
-  example "numeric helper methods are defined" do
+  example 'numeric helper methods are defined' do
     expect(@size).to respond_to(:to_kb)
     expect(@size).to respond_to(:to_mb)
     expect(@size).to respond_to(:to_gb)
     expect(@size).to respond_to(:to_tb)
   end
 
-  example "to_kb works as expected" do
+  example 'to_kb works as expected' do
     expect(@size.to_kb).to eq(57344)
   end
 
-  example "to_mb works as expected" do
+  example 'to_mb works as expected' do
     expect(@size.to_mb).to eq(56)
   end
 
-  example "to_gb works as expected" do
+  example 'to_gb works as expected' do
     expect(@size.to_gb).to eq(0)
   end
 
-  context "Filesystem.stat(Pathname)" do
+  context 'Filesystem.stat(Pathname)' do
     before do
-      @stat_pathname = Sys::Filesystem.stat(Pathname.new(root))
+      @stat_pathname = described_class.stat(Pathname.new(root))
     end
 
-    example "stat with Pathname argument works as expected" do
+    example 'class returns expected value with pathname argument' do
       expect(@stat_pathname.class).to eq(@stat.class)
+    end
+
+    example 'path returns expected value with pathname argument' do
       expect(@stat_pathname.path).to eq(@stat.path)
+    end
+
+    example 'block_size returns expected value with pathname argument' do
       expect(@stat_pathname.block_size).to eq(@stat.block_size)
+    end
+
+    example 'fragment_size returns expected value with pathname argument' do
       expect(@stat_pathname.fragment_size).to eq(@stat.fragment_size)
+    end
+
+    example 'blocks returns expected value with pathname argument' do
       expect(@stat_pathname.blocks).to eq(@stat.blocks)
+    end
+
+    example 'blocks_free returns expected value with pathname argument' do
       expect(@stat_pathname.blocks_free).to eq(@stat.blocks_free)
+    end
+
+    example 'blocks_available returns expected value with pathname argument' do
       expect(@stat_pathname.blocks_available).to eq(@stat.blocks_available)
+    end
+
+    example 'files returns expected value with pathname argument' do
       expect(@stat_pathname.files).to eq(@stat.files)
+    end
+
+    example 'files_free returns expected value with pathname argument' do
       expect(@stat_pathname.files_free).to eq(@stat.files_free)
+    end
+
+    example 'files_available returns expected value with pathname argument' do
       expect(@stat_pathname.files_available).to eq(@stat.files_available)
+    end
+
+    example 'filesystem_id returns expected value with pathname argument' do
       expect(@stat_pathname.filesystem_id).to eq(@stat.filesystem_id)
+    end
+
+    example 'flags returns expected value with pathname argument' do
       expect(@stat_pathname.flags).to eq(@stat.flags)
+    end
+
+    example 'name_max returns expected value with pathname argument' do
       expect(@stat_pathname.name_max).to eq(@stat.name_max)
+    end
+
+    example 'base_type returns expected value with pathname argument' do
       expect(@stat_pathname.base_type).to eq(@stat.base_type)
     end
   end
 
-  context "Filesystem.stat(File)" do
+  context 'Filesystem.stat(File)' do
     before do
-      @stat_file = File.open(root){ |file| Sys::Filesystem.stat(file) }
+      @stat_file = File.open(root){ |file| described_class.stat(file) }
     end
 
-    example "stat with File argument works as expected" do
+    example 'class returns expected value with file argument' do
       expect(@stat_file.class).to eq(@stat.class)
+    end
+
+    example 'path returns expected value with file argument' do
       expect(@stat_file.path).to eq(@stat.path)
+    end
+
+    example 'block_size returns expected value with file argument' do
       expect(@stat_file.block_size).to eq(@stat.block_size)
+    end
+
+    example 'fragment_size returns expected value with file argument' do
       expect(@stat_file.fragment_size).to eq(@stat.fragment_size)
+    end
+
+    example 'blocks returns expected value with file argument' do
       expect(@stat_file.blocks).to eq(@stat.blocks)
+    end
+
+    example 'blocks_free returns expected value with file argument' do
       expect(@stat_file.blocks_free).to eq(@stat.blocks_free)
+    end
+
+    example 'blocks_available returns expected value with file argument' do
       expect(@stat_file.blocks_available).to eq(@stat.blocks_available)
+    end
+
+    example 'files returns expected value with file argument' do
       expect(@stat_file.files).to eq(@stat.files)
+    end
+
+    example 'files_free returns expected value with file argument' do
       expect(@stat_file.files_free).to eq(@stat.files_free)
+    end
+
+    example 'files_available returns expected value with file argument' do
       expect(@stat_file.files_available).to eq(@stat.files_available)
+    end
+
+    example 'filesystem_id returns expected value with file argument' do
       expect(@stat_file.filesystem_id).to eq(@stat.filesystem_id)
+    end
+
+    example 'flags returns expected value with file argument' do
       expect(@stat_file.flags).to eq(@stat.flags)
+    end
+
+    example 'name_max returns expected value with file argument' do
       expect(@stat_file.name_max).to eq(@stat.name_max)
+    end
+
+    example 'base_type returns expected value with file argument' do
       expect(@stat_file.base_type).to eq(@stat.base_type)
     end
   end
 
-  context "Filesystem.stat(Dir)" do
+  context 'Filesystem.stat(Dir)' do
     before do
-      @stat_dir = Dir.open(root){ |dir| Sys::Filesystem.stat(dir) }
+      @stat_dir = Dir.open(root){ |dir| described_class.stat(dir) }
     end
 
-    example "stat with Dir argument works as expected" do
+    example 'class returns expected value with Dir argument' do
       expect(@stat_dir.class).to eq(@stat.class)
+    end
+
+    example 'path returns expected value with Dir argument' do
       expect(@stat_dir.path).to eq(@stat.path)
+    end
+
+    example 'block_size returns expected value with Dir argument' do
       expect(@stat_dir.block_size).to eq(@stat.block_size)
+    end
+
+    example 'fragment_size returns expected value with Dir argument' do
       expect(@stat_dir.fragment_size).to eq(@stat.fragment_size)
+    end
+
+    example 'blocks returns expected value with Dir argument' do
       expect(@stat_dir.blocks).to eq(@stat.blocks)
+    end
+
+    example 'blocks_free returns expected value with Dir argument' do
       expect(@stat_dir.blocks_free).to eq(@stat.blocks_free)
+    end
+
+    example 'blocks_available returns expected value with Dir argument' do
       expect(@stat_dir.blocks_available).to eq(@stat.blocks_available)
+    end
+
+    example 'files returns expected value with Dir argument' do
       expect(@stat_dir.files).to eq(@stat.files)
+    end
+
+    example 'files_free returns expected value with Dir argument' do
       expect(@stat_dir.files_free).to eq(@stat.files_free)
+    end
+
+    example 'files_available returns expected value with Dir argument' do
       expect(@stat_dir.files_available).to eq(@stat.files_available)
+    end
+
+    example 'filesystem_id returns expected value with Dir argument' do
       expect(@stat_dir.filesystem_id).to eq(@stat.filesystem_id)
+    end
+
+    example 'flags returns expected value with Dir argument' do
       expect(@stat_dir.flags).to eq(@stat.flags)
+    end
+
+    example 'name_max returns expected value with Dir argument' do
       expect(@stat_dir.name_max).to eq(@stat.name_max)
+    end
+
+    example 'base_type returns expected value with Dir argument' do
       expect(@stat_dir.base_type).to eq(@stat.base_type)
     end
   end
 
-  context "Filesystem::Mount" do
-    let(:mount){ Sys::Filesystem.mounts[0] }
+  context 'Filesystem::Mount' do
+    let(:mount){ described_class.mounts[0] }
 
     before do
       @array = []
     end
 
-    example "mounts singleton method works as expected without a block" do
-      expect{ @array = Sys::Filesystem.mounts }.not_to raise_error
+    example 'mounts singleton method works as expected without a block' do
+      expect{ @array = described_class.mounts }.not_to raise_error
       expect(@array[0]).to be_kind_of(Sys::Filesystem::Mount)
     end
 
-    example "mounts singleton method works as expected with a block" do
-      expect{ Sys::Filesystem.mounts{ |m| @array << m } }.not_to raise_error
+    example 'mounts singleton method works as expected with a block' do
+      expect{ described_class.mounts{ |m| @array << m } }.not_to raise_error
       expect(@array[0]).to be_kind_of(Sys::Filesystem::Mount)
     end
 
-    example "calling the mounts singleton method a large number of times does not cause issues" do
-      expect{ 1000.times{ @array = Sys::Filesystem.mounts } }.not_to raise_error
+    example 'calling the mounts singleton method a large number of times does not cause issues' do
+      expect{ 1000.times{ @array = described_class.mounts } }.not_to raise_error
     end
 
-    example "mount name method works as expected" do
+    example 'mount name method works as expected' do
       expect(mount).to respond_to(:name)
       expect(mount.name).to be_kind_of(String)
     end
 
-    example "mount fsname is an alias for name" do
+    example 'mount fsname is an alias for name' do
       expect(mount).to respond_to(:fsname)
       expect(mount.method(:fsname)).to eq(mount.method(:name))
     end
 
-    example "mount point method works as expected" do
+    example 'mount point method works as expected' do
       expect(mount).to respond_to(:mount_point)
       expect(mount.mount_point).to be_kind_of(String)
     end
 
-    example "mount dir is an alias for mount_point" do
+    example 'mount dir is an alias for mount_point' do
       expect(mount).to respond_to(:dir)
       expect(mount.method(:dir)).to eq(mount.method(:mount_point))
     end
 
-    example "mount mount_type works as expected" do
+    example 'mount mount_type works as expected' do
       expect(mount).to respond_to(:mount_type)
       expect(mount.mount_type).to be_kind_of(String)
     end
 
-    example "mount options works as expected" do
+    example 'mount options works as expected' do
       expect(mount).to respond_to(:options)
       expect(mount.options).to be_kind_of(String)
     end
 
-    example "mount opts is an alias for options" do
+    example 'mount opts is an alias for options' do
       expect(mount).to respond_to(:opts)
       expect(mount.method(:opts)).to eq(mount.method(:options))
     end
 
-    example "mount time works as expected" do
+    example 'mount time works as expected' do
+      expected_class = solaris ? Time : NilClass
       expect(mount).to respond_to(:mount_time)
-
-      if solaris
-        expect(mount.mount_time).to be_kind_of(Time)
-      else
-        expect(mount.mount_time).to be_nil
-      end
+      expect(mount.mount_time).to be_kind_of(expected_class)
     end
 
-    example "mount dump_frequency works as expected" do
+    example 'mount dump_frequency works as expected' do
       msg = 'dump_frequency test skipped on this platform'
       skip msg if solaris || bsd || darwin
       expect(mount).to respond_to(:dump_frequency)
       expect(mount.dump_frequency).to be_kind_of(Numeric)
     end
 
-    example "mount freq is an alias for dump_frequency" do
+    example 'mount freq is an alias for dump_frequency' do
       expect(mount).to respond_to(:freq)
       expect(mount.method(:freq)).to eq(mount.method(:dump_frequency))
     end
 
-    example "mount pass_number works as expected" do
+    example 'mount pass_number works as expected' do
       msg = 'pass_number test skipped on this platform'
       skip msg if solaris || bsd || darwin
       expect(mount).to respond_to(:pass_number)
       expect(mount.pass_number).to be_kind_of(Numeric)
     end
 
-    example "mount passno is an alias for pass_number" do
+    example 'mount passno is an alias for pass_number' do
       expect(mount).to respond_to(:passno)
       expect(mount.method(:passno)).to eq(mount.method(:pass_number))
     end
 
-    example "mount_point singleton method works as expected" do
-      expect(Sys::Filesystem).to respond_to(:mount_point)
-      expect{ Sys::Filesystem.mount_point(Dir.pwd) }.not_to raise_error
-      expect(Sys::Filesystem.mount_point(Dir.pwd)).to be_kind_of(String)
+    example 'mount_point singleton method works as expected' do
+      expect(described_class).to respond_to(:mount_point)
+      expect{ described_class.mount_point(Dir.pwd) }.not_to raise_error
+      expect(described_class.mount_point(Dir.pwd)).to be_kind_of(String)
     end
 
-    example "mount singleton method is defined" do
-      expect(Sys::Filesystem).to respond_to(:mount)
+    example 'mount singleton method is defined' do
+      expect(described_class).to respond_to(:mount)
     end
 
-    example "umount singleton method is defined" do
-      expect(Sys::Filesystem).to respond_to(:umount)
+    example 'umount singleton method is defined' do
+      expect(described_class).to respond_to(:umount)
     end
   end
 
-  context "FFI" do
+  context 'FFI' do
     before(:context) do
       require 'mkmf-lite'
     end
 
     let(:dummy) { Class.new { extend Mkmf::Lite } }
 
-    example "ffi functions are private" do
-      expect(Sys::Filesystem.methods.include?('statvfs')).to be false
-      expect(Sys::Filesystem.methods.include?('strerror')).to be false
+    example 'ffi functions are private' do
+      expect(described_class.methods.include?('statvfs')).to be false
+      expect(described_class.methods.include?('strerror')).to be false
     end
 
-    example "statfs struct is expected size" do
+    example 'statfs struct is expected size' do
       header = bsd || darwin ? 'sys/mount.h' : 'sys/statfs.h'
       expect(Sys::Filesystem::Structs::Statfs.size).to eq(dummy.check_sizeof('struct statfs', header))
     end
 
-    example "statvfs struct is expected size" do
+    example 'statvfs struct is expected size' do
       expect(Sys::Filesystem::Structs::Statvfs.size).to eq(dummy.check_sizeof('struct statvfs', 'sys/statvfs.h'))
     end
 
-    example "mnttab struct is expected size" do
-      skip "mnttab test skipped except on Solaris" unless solaris
+    example 'mnttab struct is expected size' do
+      skip 'mnttab test skipped except on Solaris' unless solaris
       expect(Sys::Filesystem::Structs::Mnttab.size).to eq(dummy.check_sizeof('struct mnttab', 'sys/mnttab.h'))
     end
 
-    example "mntent struct is expected size" do
-      skip "mnttab test skipped except on Linux" unless linux
+    example 'mntent struct is expected size' do
+      skip 'mnttab test skipped except on Linux' unless linux
       expect(Sys::Filesystem::Structs::Mntent.size).to eq(dummy.check_sizeof('struct mntent', 'mntent.h'))
     end
+
+    example 'a failed statvfs call behaves as expected' do
+      allow(described_class).to receive(:statvfs).and_return(-1)
+      if ENV['CI']
+        msg = 'statvfs() function failed: Inappropriate ioctl for device'
+      else
+        msg = 'statvfs() function failed: No such file or directory'
+      end
+      expect{ described_class.stat('/whatever') }.to raise_error(Sys::Filesystem::Error, msg)
+    end
   end
 end
diff --git a/spec/sys_filesystem_windows_spec.rb b/spec/sys_filesystem_windows_spec.rb
index 97465c9..1694e6c 100644
--- a/spec/sys_filesystem_windows_spec.rb
+++ b/spec/sys_filesystem_windows_spec.rb
@@ -1,3 +1,5 @@
+# frozen_string_literal: true
+
 ####################################################################
 # sys_filesystem_windows_spec.rb
 #
@@ -12,337 +14,447 @@ RSpec.describe Sys::Filesystem, :windows => true do
   let(:root) { 'C:/' }
 
   before do
-    @stat  = Sys::Filesystem.stat(root)
+    @stat  = described_class.stat(root)
     @size  = 58720256
   end
 
-  example "version number is set to the expected value" do
-    expect(Sys::Filesystem::VERSION).to eq('1.4.3')
-    expect(Sys::Filesystem::VERSION).to be_frozen
-  end
-
-  example "you cannot instantiate an instance" do
-    expect{ described_class.new }.to raise_error(NoMethodError)
-  end
-
-  example "stat path works as expected" do
+  example 'stat path works as expected' do
     expect(@stat).to respond_to(:path)
     expect(@stat.path).to eq(root)
   end
 
-  example "stat block_size works as expected" do
+  example 'stat block_size works as expected' do
     expect(@stat).to respond_to(:block_size)
     expect(@stat.block_size).to be_kind_of(Numeric)
   end
 
-  example "stat works with or without trailing slash on standard paths" do
-    expect(Sys::Filesystem.stat("C:/").path).to eq("C:/")
-    expect(Sys::Filesystem.stat("C:/Users").path).to eq("C:/Users")
-    expect(Sys::Filesystem.stat("C:/Users/").path).to eq("C:/Users/")
-    expect(Sys::Filesystem.stat("C:/Users/").path).to eq("C:/Users/")
+  example 'stat works with or without trailing slash on standard paths' do
+    expect(described_class.stat('C:/').path).to eq('C:/')
+    expect(described_class.stat('C:/Users').path).to eq('C:/Users')
+    expect(described_class.stat('C:/Users/').path).to eq('C:/Users/')
+    expect(described_class.stat('C:/Users/').path).to eq('C:/Users/')
   end
 
-  example "stat works with or without trailing slash on UNC paths" do
-    expect(Sys::Filesystem.stat("//127.0.0.1/C$").path).to eq("//127.0.0.1/C$")
-    expect(Sys::Filesystem.stat("//127.0.0.1/C$/").path).to eq("//127.0.0.1/C$/")
-    expect(Sys::Filesystem.stat("\\\\127.0.0.1\\C$").path).to eq("\\\\127.0.0.1\\C$")
-    expect(Sys::Filesystem.stat("\\\\127.0.0.1\\C$\\").path).to eq("\\\\127.0.0.1\\C$\\")
+  example 'stat works with or without trailing slash on UNC paths' do
+    expect(described_class.stat('//127.0.0.1/C$').path).to eq('//127.0.0.1/C$')
+    expect(described_class.stat('//127.0.0.1/C$/').path).to eq('//127.0.0.1/C$/')
+    expect(described_class.stat('\\\\127.0.0.1\\C$').path).to eq('\\\\127.0.0.1\\C$')
+    expect(described_class.stat('\\\\127.0.0.1\\C$\\').path).to eq('\\\\127.0.0.1\\C$\\')
   end
 
-  example "stat fragment_size works as expected" do
+  example 'stat fragment_size works as expected' do
     expect(@stat).to respond_to(:fragment_size)
     expect(@stat.fragment_size).to be_nil
   end
 
-  example "stat blocks works as expected" do
+  example 'stat blocks works as expected' do
     expect(@stat).to respond_to(:blocks)
     expect(@stat.blocks).to be_kind_of(Numeric)
   end
 
-  example "stat blocks_free works as expected" do
+  example 'stat blocks_free works as expected' do
     expect(@stat).to respond_to(:blocks_free)
     expect(@stat.blocks_free).to be_kind_of(Numeric)
   end
 
-  example "stat blocks_available works as expected" do
+  example 'stat blocks_available works as expected' do
     expect(@stat).to respond_to(:blocks_available)
     expect(@stat.blocks_available).to be_kind_of(Numeric)
   end
 
-  example "block stats return expected relative values" do
+  example 'block stats return expected relative values' do
     expect(@stat.blocks >= @stat.blocks_free).to be true
     expect(@stat.blocks_free >= @stat.blocks_available).to be true
   end
 
-  example "stat files works as expected" do
+  example 'stat files works as expected' do
     expect(@stat).to respond_to(:files)
     expect(@stat.files).to be_nil
   end
 
-  example "stat inodes is an alias for files" do
+  example 'stat inodes is an alias for files' do
     expect(@stat.method(:inodes)).to eq(@stat.method(:files))
   end
 
-  example "stat files_free works as expected" do
+  example 'stat files_free works as expected' do
     expect(@stat).to respond_to(:files_free)
     expect(@stat.files_free).to be_nil
   end
 
-  example "stat inodes_free is an alias for files_free" do
+  example 'stat inodes_free is an alias for files_free' do
     expect(@stat).to respond_to(:inodes_free)
   end
 
-  example "stat files available works as expected" do
+  example 'stat files available works as expected' do
     expect(@stat).to respond_to(:files_available)
     expect(@stat.files_available).to be_nil
   end
 
-  example "stat inodes_available is an alias for files_available" do
+  example 'stat inodes_available is an alias for files_available' do
     expect(@stat.method(:inodes_available)).to eq(@stat.method(:files_available))
   end
 
-  example "stat filesystem_id works as expected" do
+  example 'stat filesystem_id works as expected' do
     expect(@stat).to respond_to(:filesystem_id)
     expect(@stat.filesystem_id).to be_kind_of(Integer)
   end
 
-  example "stat flags works as expected" do
+  example 'stat flags works as expected' do
     expect(@stat).to respond_to(:flags)
     expect(@stat.flags).to be_kind_of(Numeric)
   end
 
-  example "stat name_max works as expected" do
+  example 'stat name_max works as expected' do
     expect(@stat).to respond_to(:name_max)
     expect(@stat.name_max).to be_kind_of(Numeric)
   end
 
-  example "stat base_type works as expected" do
+  example 'stat base_type works as expected' do
     expect(@stat).to respond_to(:base_type)
     expect(@stat.base_type).to be_kind_of(String)
   end
 
-  example "stat bytes_total basic functionality" do
+  example 'stat bytes_total basic functionality' do
     expect(@stat).to respond_to(:bytes_total)
     expect(@stat.bytes_total).to be_kind_of(Numeric)
   end
 
-  example "stat bytes_free basic functionality" do
+  example 'stat bytes_free basic functionality' do
     expect(@stat).to respond_to(:bytes_free)
     expect(@stat.bytes_free).to be_kind_of(Numeric)
     expect(@stat.blocks_free * @stat.block_size).to eq(@stat.bytes_free)
   end
 
-  example "stat bytes_available basic functionality" do
+  example 'stat bytes_available basic functionality' do
     expect(@stat).to respond_to(:bytes_available)
     expect(@stat.bytes_available).to be_kind_of(Numeric)
     expect(@stat.blocks_available * @stat.block_size).to eq(@stat.bytes_available)
   end
 
-  example "stat bytes_used basic functionality" do
+  example 'stat bytes_used basic functionality' do
     expect(@stat).to respond_to(:bytes_used)
     expect(@stat.bytes_used).to be_kind_of(Numeric)
   end
 
-  example "stat percent_used basic functionality" do
+  example 'stat percent_used basic functionality' do
     expect(@stat).to respond_to(:percent_used)
     expect(@stat.percent_used).to be_kind_of(Float)
   end
 
-  example "case_insensitive returns expected result" do
+  example 'case_insensitive returns expected result' do
     expect(@stat).to respond_to(:case_insensitive?)
-    expect(@stat.case_insensitive?).to eq(true)
+    expect(@stat.case_insensitive?).to be(true)
   end
 
-  context "Filesystem.stat(Pathname)" do
+  context 'Filesystem.stat(Pathname)' do
     before do
-      @stat_pathname = Sys::Filesystem.stat(Pathname.new(root))
+      @stat_pathname = described_class.stat(Pathname.new(root))
     end
 
-    example "stat with Pathname argument works as expected" do
+    example 'class returns expected value with pathname argument' do
       expect(@stat_pathname.class).to eq(@stat.class)
+    end
+
+    example 'path returns expected value with pathname argument' do
       expect(@stat_pathname.path).to eq(@stat.path)
+    end
+
+    example 'block_size returns expected value with pathname argument' do
       expect(@stat_pathname.block_size).to eq(@stat.block_size)
+    end
+
+    example 'fragment_size returns expected value with pathname argument' do
       expect(@stat_pathname.fragment_size).to eq(@stat.fragment_size)
+    end
+
+    example 'blocks returns expected value with pathname argument' do
       expect(@stat_pathname.blocks).to eq(@stat.blocks)
+    end
+
+    example 'blocks_free returns expected value with pathname argument' do
       expect(@stat_pathname.blocks_free).to eq(@stat.blocks_free)
+    end
+
+    example 'blocks_available returns expected value with pathname argument' do
       expect(@stat_pathname.blocks_available).to eq(@stat.blocks_available)
+    end
+
+    example 'files returns expected value with pathname argument' do
       expect(@stat_pathname.files).to eq(@stat.files)
+    end
+
+    example 'files_free returns expected value with pathname argument' do
       expect(@stat_pathname.files_free).to eq(@stat.files_free)
+    end
+
+    example 'files_available returns expected value with pathname argument' do
       expect(@stat_pathname.files_available).to eq(@stat.files_available)
+    end
+
+    example 'filesystem_id returns expected value with pathname argument' do
       expect(@stat_pathname.filesystem_id).to eq(@stat.filesystem_id)
+    end
+
+    example 'flags returns expected value with pathname argument' do
       expect(@stat_pathname.flags).to eq(@stat.flags)
+    end
+
+    example 'name_max returns expected value with pathname argument' do
       expect(@stat_pathname.name_max).to eq(@stat.name_max)
+    end
+
+    example 'base_type returns expected value with pathname argument' do
       expect(@stat_pathname.base_type).to eq(@stat.base_type)
     end
   end
 
-  context "Filesystem.stat(Dir)" do
+  context 'Filesystem.stat(Dir)' do
     before do
-      @stat_dir = Dir.open(root){ |dir| Sys::Filesystem.stat(dir) }
+      @stat_dir = Dir.open(root){ |dir| described_class.stat(dir) }
+    end
+
+    example 'stat class with Dir argument works as expected' do
+      expect(@stat_dir.class).to eq(@stat.class)
+    end
+
+    example 'stat path with Dir argument works as expected' do
+      expect(@stat_dir.path).to eq(@stat.path)
+    end
+
+    example 'stat block_size with Dir argument works as expected' do
+      expect(@stat_dir.block_size).to eq(@stat.block_size)
+    end
+
+    example 'stat fragment_size with Dir argument works as expected' do
+      expect(@stat_dir.fragment_size).to eq(@stat.fragment_size)
+    end
+
+    example 'stat blocks with Dir argument works as expected' do
+      expect(@stat_dir.blocks).to eq(@stat.blocks)
+    end
+
+    example 'stat blocks_free with Dir argument works as expected' do
+      expect(@stat_dir.blocks_free).to eq(@stat.blocks_free)
+    end
+
+    example 'stat blocks_available with Dir argument works as expected' do
+      expect(@stat_dir.blocks_available).to eq(@stat.blocks_available)
+    end
+
+    example 'stat files with Dir argument works as expected' do
+      expect(@stat_dir.files).to eq(@stat.files)
+    end
+
+    example 'stat files_free with Dir argument works as expected' do
+      expect(@stat_dir.files_free).to eq(@stat.files_free)
+    end
+
+    example 'stat files_available with Dir argument works as expected' do
+      expect(@stat_dir.files_available).to eq(@stat.files_available)
+    end
+
+    example 'stat filesystem_id with Dir argument works as expected' do
+      expect(@stat_dir.filesystem_id).to eq(@stat.filesystem_id)
     end
 
-    example "stat with Dir argument works as expected" do
-      expect( @stat_dir.class).to eq(@stat.class)
-      expect( @stat_dir.path).to eq(@stat.path)
-      expect( @stat_dir.block_size).to eq(@stat.block_size)
-      expect( @stat_dir.fragment_size).to eq(@stat.fragment_size)
-      expect( @stat_dir.blocks).to eq(@stat.blocks)
-      expect( @stat_dir.blocks_free).to eq(@stat.blocks_free)
-      expect( @stat_dir.blocks_available).to eq(@stat.blocks_available)
-      expect( @stat_dir.files).to eq(@stat.files)
-      expect( @stat_dir.files_free).to eq(@stat.files_free)
-      expect( @stat_dir.files_available).to eq(@stat.files_available)
-      expect( @stat_dir.filesystem_id).to eq(@stat.filesystem_id)
-      expect( @stat_dir.flags).to eq(@stat.flags)
-      expect( @stat_dir.name_max).to eq(@stat.name_max)
-      expect( @stat_dir.base_type).to eq(@stat.base_type)
+    example 'stat flags with Dir argument works as expected' do
+      expect(@stat_dir.flags).to eq(@stat.flags)
+    end
+
+    example 'stat name_max with Dir argument works as expected' do
+      expect(@stat_dir.name_max).to eq(@stat.name_max)
+    end
+
+    example 'stat base_type with Dir argument works as expected' do
+      expect(@stat_dir.base_type).to eq(@stat.base_type)
     end
   end
 
-  context "mount_point" do
-    example "mount_point singleton method basic functionality" do
-      expect(Sys::Filesystem).to respond_to(:mount_point)
-      expect{ Sys::Filesystem.mount_point(Dir.pwd) }.not_to raise_error
-      expect(Sys::Filesystem.mount_point(Dir.pwd)).to be_kind_of(String)
+  context 'mount_point' do
+    example 'mount_point singleton method basic functionality' do
+      expect(described_class).to respond_to(:mount_point)
+      expect{ described_class.mount_point(Dir.pwd) }.not_to raise_error
+      expect(described_class.mount_point(Dir.pwd)).to be_kind_of(String)
     end
 
-    example "mount_point singleton method returns expected value" do
-      expect(Sys::Filesystem.mount_point("C:\\Users\\foo")).to eq("C:\\")
-      expect(Sys::Filesystem.mount_point("//foo/bar/baz")).to eq("\\\\foo\\bar")
+    example 'mount_point singleton method returns expected value' do
+      expect(described_class.mount_point('C:\\Users\\foo')).to eq('C:\\')
+      expect(described_class.mount_point('//foo/bar/baz')).to eq('\\\\foo\\bar')
     end
 
-    example "mount_point works with Pathname object" do
-      expect{ Sys::Filesystem.mount_point(Pathname.new("C:/Users/foo")) }.not_to raise_error
-      expect(Sys::Filesystem.mount_point("C:\\Users\\foo")).to eq("C:\\")
-      expect(Sys::Filesystem.mount_point("//foo/bar/baz")).to eq("\\\\foo\\bar")
+    example 'mount_point works with Pathname object' do
+      expect{ described_class.mount_point(Pathname.new('C:/Users/foo')) }.not_to raise_error
+      expect(described_class.mount_point('C:\\Users\\foo')).to eq('C:\\')
+      expect(described_class.mount_point('//foo/bar/baz')).to eq('\\\\foo\\bar')
     end
   end
 
-  example "filesystem constants are defined" do
-    expect(Sys::Filesystem::CASE_SENSITIVE_SEARCH).not_to be_nil
-    expect(Sys::Filesystem::CASE_PRESERVED_NAMES).not_to be_nil
-    expect(Sys::Filesystem::UNICODE_ON_DISK).not_to be_nil
-    expect(Sys::Filesystem::PERSISTENT_ACLS).not_to be_nil
-    expect(Sys::Filesystem::FILE_COMPRESSION).not_to be_nil
-    expect(Sys::Filesystem::VOLUME_QUOTAS).not_to be_nil
-    expect(Sys::Filesystem::SUPPORTS_SPARSE_FILES).not_to be_nil
-    expect(Sys::Filesystem::SUPPORTS_REPARSE_POINTS).not_to be_nil
-    expect(Sys::Filesystem::SUPPORTS_REMOTE_STORAGE).not_to be_nil
-    expect(Sys::Filesystem::VOLUME_IS_COMPRESSED).not_to be_nil
-    expect(Sys::Filesystem::SUPPORTS_OBJECT_IDS).not_to be_nil
-    expect(Sys::Filesystem::SUPPORTS_ENCRYPTION).not_to be_nil
-    expect(Sys::Filesystem::NAMED_STREAMS).not_to be_nil
-    expect(Sys::Filesystem::READ_ONLY_VOLUME).not_to be_nil
+  context 'filesystem constants are defined' do
+    example 'CASE_SENSITIVE_SEARCH' do
+      expect(Sys::Filesystem::CASE_SENSITIVE_SEARCH).not_to be_nil
+    end
+
+    example 'CASE_PRESERVED_NAMES' do
+      expect(Sys::Filesystem::CASE_PRESERVED_NAMES).not_to be_nil
+    end
+
+    example 'UNICODE_ON_DISK' do
+      expect(Sys::Filesystem::UNICODE_ON_DISK).not_to be_nil
+    end
+
+    example 'PERSISTENT_ACLS' do
+      expect(Sys::Filesystem::PERSISTENT_ACLS).not_to be_nil
+    end
+
+    example 'FILE_COMPRESSION' do
+      expect(Sys::Filesystem::FILE_COMPRESSION).not_to be_nil
+    end
+
+    example 'VOLUME_QUOTAS' do
+      expect(Sys::Filesystem::VOLUME_QUOTAS).not_to be_nil
+    end
+
+    example 'SUPPORTS_SPARSE_FILES' do
+      expect(Sys::Filesystem::SUPPORTS_SPARSE_FILES).not_to be_nil
+    end
+
+    example 'SUPPORTS_REPARSE_POINTS' do
+      expect(Sys::Filesystem::SUPPORTS_REPARSE_POINTS).not_to be_nil
+    end
+
+    example 'SUPPORTS_REMOTE_STORAGE' do
+      expect(Sys::Filesystem::SUPPORTS_REMOTE_STORAGE).not_to be_nil
+    end
+
+    example 'VOLUME_IS_COMPRESSED' do
+      expect(Sys::Filesystem::VOLUME_IS_COMPRESSED).not_to be_nil
+    end
+
+    example 'SUPPORTS_OBJECT_IDS' do
+      expect(Sys::Filesystem::SUPPORTS_OBJECT_IDS).not_to be_nil
+    end
+
+    example 'SUPPORTS_ENCRYPTION' do
+      expect(Sys::Filesystem::SUPPORTS_ENCRYPTION).not_to be_nil
+    end
+
+    example 'NAMED_STREAMS' do
+      expect(Sys::Filesystem::NAMED_STREAMS).not_to be_nil
+    end
+
+    example 'READ_ONLY_VOLUME' do
+      expect(Sys::Filesystem::READ_ONLY_VOLUME).not_to be_nil
+    end
   end
 
-  example "stat singleton method defaults to root path if proviced" do
-    expect{ Sys::Filesystem.stat("C://Program Files") }.not_to raise_error
+  example 'stat singleton method defaults to root path if proviced' do
+    expect{ described_class.stat('C://Program Files') }.not_to raise_error
   end
 
-  example "stat singleton method accepts a Pathname object" do
-    expect{ Sys::Filesystem.stat(Pathname.new("C://Program Files")) }.not_to raise_error
+  example 'stat singleton method accepts a Pathname object' do
+    expect{ described_class.stat(Pathname.new('C://Program Files')) }.not_to raise_error
   end
 
-  example "stat singleton method requires a single argument" do
-    expect{ Sys::Filesystem.stat }.to raise_error(ArgumentError)
-    expect{ Sys::Filesystem.stat(Dir.pwd, Dir.pwd) }.to raise_error(ArgumentError)
+  example 'stat singleton method requires a single argument' do
+    expect{ described_class.stat }.to raise_error(ArgumentError)
+    expect{ described_class.stat(Dir.pwd, Dir.pwd) }.to raise_error(ArgumentError)
   end
 
-  example "stat singleton method raises an error if path is not found" do
-    expect{ Sys::Filesystem.stat("C://Bogus//Dir") }.to raise_error(Errno::ESRCH)
+  example 'stat singleton method raises an error if path is not found' do
+    expect{ described_class.stat('C://Bogus//Dir') }.to raise_error(Errno::ESRCH)
   end
 
-  context "Filesystem::Mount" do
-    let(:mount){ Sys::Filesystem.mounts[0] }
+  context 'Filesystem::Mount' do
+    let(:mount){ described_class.mounts[0] }
 
     before do
       @array = []
     end
 
-    example "mount singleton method exists" do
-      expect(Sys::Filesystem).to respond_to(:mount)
+    example 'mount singleton method exists' do
+      expect(described_class).to respond_to(:mount)
     end
 
-    example "umount singleton method exists" do
-      expect(Sys::Filesystem).to respond_to(:umount)
+    example 'umount singleton method exists' do
+      expect(described_class).to respond_to(:umount)
     end
 
-    example "mounts singleton method basic functionality" do
-      expect(Sys::Filesystem).to respond_to(:mounts)
-      expect{ Sys::Filesystem.mounts }.not_to raise_error
-      expect{ Sys::Filesystem.mounts{}.not_to raise_error }
+    example 'mounts singleton method basic functionality' do
+      expect(described_class).to respond_to(:mounts)
+      expect{ described_class.mounts }.not_to raise_error
+      expect{ described_class.mounts{} }.not_to raise_error
     end
 
-    example "mounts singleton method returns the expected value" do
-      expect(Sys::Filesystem.mounts).to be_kind_of(Array)
-      expect(Sys::Filesystem.mounts[0]).to be_kind_of(Sys::Filesystem::Mount)
+    example 'mounts singleton method returns the expected value' do
+      expect(described_class.mounts).to be_kind_of(Array)
+      expect(described_class.mounts[0]).to be_kind_of(Sys::Filesystem::Mount)
     end
 
-    example "mounts singleton method works as expected when a block is provided" do
-      expect(Sys::Filesystem.mounts{}).to be_nil
-      expect{ Sys::Filesystem.mounts{ |mt| @array << mt } }.not_to raise_error
+    example 'mounts singleton method works as expected when a block is provided' do
+      expect(described_class.mounts{}).to be_nil
+      expect{ described_class.mounts{ |mt| @array << mt } }.not_to raise_error
       expect(@array[0]).to be_kind_of(Sys::Filesystem::Mount)
     end
 
-    example "mount name works as expected" do
+    example 'mount name works as expected' do
       expect(mount).to respond_to(:name)
       expect(mount.name).to be_kind_of(String)
     end
 
-    example "mount_time works as expected" do
+    example 'mount_time works as expected' do
       expect(mount).to respond_to(:mount_time)
       expect(mount.mount_time).to be_kind_of(Time)
     end
 
-    example "mount type works as expected" do
+    example 'mount type works as expected' do
       expect(mount).to respond_to(:mount_type)
       expect(mount.mount_type).to be_kind_of(String)
     end
 
-    example "mount point works as expected" do
+    example 'mount point works as expected' do
       expect(mount).to respond_to(:mount_point)
       expect(mount.mount_point).to be_kind_of(String)
     end
 
-    example "mount options works as expected" do
+    example 'mount options works as expected' do
       expect(mount).to respond_to(:options)
       expect(mount.options).to be_kind_of(String)
     end
 
-    example "mount pass_number works as expected" do
+    example 'mount pass_number works as expected' do
       expect(mount).to respond_to(:pass_number)
       expect(mount.pass_number).to be_nil
     end
 
-    example "mount frequency works as expected" do
+    example 'mount frequency works as expected' do
       expect(mount).to respond_to(:frequency)
       expect(mount.frequency).to be_nil
     end
 
-    example "mounts singleton method does not accept any arguments" do
-      expect{ Sys::Filesystem.mounts("C:\\") }.to raise_error(ArgumentError)
+    example 'mounts singleton method does not accept any arguments' do
+      expect{ described_class.mounts('C:\\') }.to raise_error(ArgumentError)
     end
   end
 
-  example "custom Numeric#to_kb method works as expected" do
+  example 'custom Numeric#to_kb method works as expected' do
     expect(@size).to respond_to(:to_kb)
     expect(@size.to_kb).to eq(57344)
   end
 
-  example "custom Numeric#to_mb method works as expected" do
+  example 'custom Numeric#to_mb method works as expected' do
     expect(@size).to respond_to(:to_mb)
     expect(@size.to_mb).to eq(56)
   end
 
-  example "custom Numeric#to_gb method works as expected" do
+  example 'custom Numeric#to_gb method works as expected' do
     expect(@size).to respond_to(:to_gb)
     expect(@size.to_gb).to eq(0)
   end
 
-  context "FFI" do
-    example "internal ffi functions are not public" do
-      expect(Sys::Filesystem.methods.include?(:GetVolumeInformationA)).to eq(false)
-      expect(Sys::Filesystem.instance_methods.include?(:GetVolumeInformationA)).to eq(false)
+  context 'FFI' do
+    example 'internal ffi functions are not public' do
+      expect(described_class.methods.include?(:GetVolumeInformationA)).to be(false)
+      expect(described_class.instance_methods.include?(:GetVolumeInformationA)).to be(false)
     end
   end
 end
diff --git a/sys-filesystem.gemspec b/sys-filesystem.gemspec
index 3f00d63..4666bb2 100644
--- a/sys-filesystem.gemspec
+++ b/sys-filesystem.gemspec
@@ -16,14 +16,21 @@ Gem::Specification.new do |spec|
   spec.add_development_dependency('mkmf-lite', '~> 0.5') unless Gem.win_platform?
   spec.add_development_dependency('rake')
   spec.add_development_dependency('rspec', '~> 3.9')
+  spec.add_development_dependency('rubocop')
+  spec.add_development_dependency('rubocop-rspec')
+
+  if RUBY_PLATFORM == 'java' && Gem.win_platform?
+    spec.add_dependency('jruby-win32ole')
+  end
 
   spec.metadata = {
-    'homepage_uri'      => 'https://github.com/djberg96/sys-filesystem',
-    'bug_tracker_uri'   => 'https://github.com/djberg96/sys-filesystem/issues',
-    'changelog_uri'     => 'https://github.com/djberg96/sys-filesystem/blob/main/CHANGES.md',
-    'documentation_uri' => 'https://github.com/djberg96/sys-filesystem/wiki',
-    'source_code_uri'   => 'https://github.com/djberg96/sys-filesystem',
-    'wiki_uri'          => 'https://github.com/djberg96/sys-filesystem/wiki'
+    'homepage_uri'          => 'https://github.com/djberg96/sys-filesystem',
+    'bug_tracker_uri'       => 'https://github.com/djberg96/sys-filesystem/issues',
+    'changelog_uri'         => 'https://github.com/djberg96/sys-filesystem/blob/main/CHANGES.md',
+    'documentation_uri'     => 'https://github.com/djberg96/sys-filesystem/wiki',
+    'source_code_uri'       => 'https://github.com/djberg96/sys-filesystem',
+    'wiki_uri'              => 'https://github.com/djberg96/sys-filesystem/wiki',
+    'rubygems_mfa_required' => 'true'
   }
 
   spec.description = <<-EOF

Debdiff

File lists identical (after any substitutions)

No differences were encountered in the control files

More details

Full run details