pax_global_header00006660000000000000000000000064143217571230014517gustar00rootroot0000000000000052 comment=25c9e47832690dca5461fd41570c53438b8a2ff6 ruby-rspec-files-1.1.3/000077500000000000000000000000001432175712300147145ustar00rootroot00000000000000ruby-rspec-files-1.1.3/.editorconfig000066400000000000000000000000641432175712300173710ustar00rootroot00000000000000root = true [*] indent_style = tab indent_size = 2 ruby-rspec-files-1.1.3/.github/000077500000000000000000000000001432175712300162545ustar00rootroot00000000000000ruby-rspec-files-1.1.3/.github/workflows/000077500000000000000000000000001432175712300203115ustar00rootroot00000000000000ruby-rspec-files-1.1.3/.github/workflows/test.yaml000066400000000000000000000016641432175712300221630ustar00rootroot00000000000000name: Test on: [push, pull_request] permissions: contents: read env: CONSOLE_OUTPUT: XTerm jobs: test: name: ${{matrix.ruby}} on ${{matrix.os}} runs-on: ${{matrix.os}}-latest continue-on-error: ${{matrix.experimental}} strategy: matrix: os: - ubuntu - macos ruby: - "2.7" - "3.0" - "3.1" experimental: [false] include: - os: ubuntu ruby: truffleruby experimental: true - os: ubuntu ruby: jruby experimental: true - os: ubuntu ruby: head experimental: true steps: - uses: actions/checkout@v3 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 10 run: bundle exec bake test ruby-rspec-files-1.1.3/.gitignore000066400000000000000000000001501432175712300167000ustar00rootroot00000000000000/.bundle/ /gems.locked /pkg/ # rspec failure tracking .rspec_status /gems.locked /.covered.db /external ruby-rspec-files-1.1.3/.rspec000066400000000000000000000000701432175712300160260ustar00rootroot00000000000000--format documentation --warnings --require spec_helper ruby-rspec-files-1.1.3/gems.rb000066400000000000000000000005211432175712300161720ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019-2022, by Samuel Williams. source 'https://rubygems.org' # Specify your gem's dependencies in rspec-files.gemspec gemspec group :maintenance, optional: true do gem "bake-modernize" gem "bake-gem" end group :test do gem "rspec" gem "bake-test" end ruby-rspec-files-1.1.3/lib/000077500000000000000000000000001432175712300154625ustar00rootroot00000000000000ruby-rspec-files-1.1.3/lib/rspec/000077500000000000000000000000001432175712300165765ustar00rootroot00000000000000ruby-rspec-files-1.1.3/lib/rspec/files.rb000066400000000000000000000004061432175712300202250ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019, by Samuel Williams. # Copyright, 2022, by Gleb Sinyavskiy. require 'rspec/core' require_relative "files/version" require_relative "files/leaks" require_relative "files/buffer" ruby-rspec-files-1.1.3/lib/rspec/files/000077500000000000000000000000001432175712300177005ustar00rootroot00000000000000ruby-rspec-files-1.1.3/lib/rspec/files/buffer.rb000066400000000000000000000010761432175712300215020ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019, by Samuel Williams. require 'securerandom' module RSpec module Files module Buffer TMP = "/tmp" def self.open(mode = 'w+', root: TMP) path = File.join(root, SecureRandom.hex(32)) file = File.open(path, mode) File.unlink(path) return file unless block_given? begin yield file ensure file.close end end end RSpec.shared_context Buffer do let(:buffer) {Buffer.open} after(:each) {buffer.close} end end end ruby-rspec-files-1.1.3/lib/rspec/files/leaks.rb000066400000000000000000000021721432175712300213260ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019-2022, by Samuel Williams. # Copyright, 2020, by Scott Tadman. module RSpec module Files module Leaks def current_ios(gc: true) GC.start if gc all_ios = ObjectSpace.each_object(::IO).to_a.sort_by(&:object_id) # We are not interested in ios that have been closed already: return all_ios.reject do |io| # It's possible to get errors if the IO is finalised. io.closed? rescue true end rescue RuntimeError => error # This occurs on JRuby. warn error.message return [] end end RSpec.shared_context Leaks do include Leaks let(:before_ios) {current_ios} let(:leaked_ios) {current_ios - before_ios} # We use around(:each) because it's the highest priority. around(:each) do |example| # Here inspect is used to avoid reporting on handles that cannot # be read from, as otherwise RSpec will attempt to test if they are # readable and get stuck forever. before_ios example.run.tap do expect(leaked_ios).to be_empty end end end end end ruby-rspec-files-1.1.3/lib/rspec/files/version.rb000066400000000000000000000002461432175712300217140ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019-2022, by Samuel Williams. module RSpec module Files VERSION = "1.1.3" end end ruby-rspec-files-1.1.3/license.md000066400000000000000000000023201432175712300166550ustar00rootroot00000000000000# MIT License Copyright, 2019-2022, by Samuel Williams. Copyright, 2019, by Cyril Roelandt. Copyright, 2020, by Olle Jonsson. Copyright, 2020, by Scott Tadman. Copyright, 2022, by Gleb Sinyavskiy. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ruby-rspec-files-1.1.3/readme.md000066400000000000000000000034621432175712300165000ustar00rootroot00000000000000# RSpec::Files Detect leaked file descriptors and provides convenient file buffers. [![Development Status](https://github.com/socketry/rspec-files/workflows/Test/badge.svg)](https://github.com/socketry/rspec-files/actions?workflow=Test) ## Installation Add this line to your application's Gemfile: ``` ruby gem 'rspec-files' ``` And then execute: $ bundle Or install it yourself as: $ gem install rspec-files Finally, add this require statement to the top of `spec/spec_helper.rb` ``` ruby require 'rspec/files' ``` ## Usage ### Leaks Leaking sockets and other kinds of IOs are a problem for long running services. `RSpec::Files::Leaks` tracks all open sockets both before and after the spec. If any are left open, a `RuntimeError` is raised and the spec fails. ``` ruby RSpec.describe "leaky ios" do include_context RSpec::Files::Leaks # The following fails: it "leaks io" do @input, @output = IO.pipe end end ``` In some cases, the Ruby garbage collector will close IOs. In the above case, it's possible that just writing `IO.pipe` will not leak as Ruby will garbage collect the resulting IOs immediately. It's still incorrect to not close IOs, so don't depend on this behaviour. ### Buffers File buffers are useful for specs which implement I/O operations. This context automatically manages a disk-based file which can be used for buffering. ``` ruby RSpec.describe "buffer" do include_context RSpec::Files::Buffer it "can read and write data" do buffer.write("Hello World") buffer.seek(0) expect(buffer.read).to be == "Hello World" end end ``` ## Contributing 1. Fork it 2. Create your feature branch (`git checkout -b my-new-feature`) 3. Commit your changes (`git commit -am 'Add some feature'`) 4. Push to the branch (`git push origin my-new-feature`) 5. Create new Pull Request ruby-rspec-files-1.1.3/release.cert000066400000000000000000000033141432175712300172140ustar00rootroot00000000000000-----BEGIN CERTIFICATE----- MIIE2DCCA0CgAwIBAgIBATANBgkqhkiG9w0BAQsFADBhMRgwFgYDVQQDDA9zYW11 ZWwud2lsbGlhbXMxHTAbBgoJkiaJk/IsZAEZFg1vcmlvbnRyYW5zZmVyMRIwEAYK CZImiZPyLGQBGRYCY28xEjAQBgoJkiaJk/IsZAEZFgJuejAeFw0yMjA4MDYwNDUz MjRaFw0zMjA4MDMwNDUzMjRaMGExGDAWBgNVBAMMD3NhbXVlbC53aWxsaWFtczEd MBsGCgmSJomT8ixkARkWDW9yaW9udHJhbnNmZXIxEjAQBgoJkiaJk/IsZAEZFgJj bzESMBAGCgmSJomT8ixkARkWAm56MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIB igKCAYEAomvSopQXQ24+9DBB6I6jxRI2auu3VVb4nOjmmHq7XWM4u3HL+pni63X2 9qZdoq9xt7H+RPbwL28LDpDNflYQXoOhoVhQ37Pjn9YDjl8/4/9xa9+NUpl9XDIW sGkaOY0eqsQm1pEWkHJr3zn/fxoKPZPfaJOglovdxf7dgsHz67Xgd/ka+Wo1YqoE e5AUKRwUuvaUaumAKgPH+4E4oiLXI4T1Ff5Q7xxv6yXvHuYtlMHhYfgNn8iiW8WN XibYXPNP7NtieSQqwR/xM6IRSoyXKuS+ZNGDPUUGk8RoiV/xvVN4LrVm9upSc0ss RZ6qwOQmXCo/lLcDUxJAgG95cPw//sI00tZan75VgsGzSWAOdjQpFM0l4dxvKwHn tUeT3ZsAgt0JnGqNm2Bkz81kG4A2hSyFZTFA8vZGhp+hz+8Q573tAR89y9YJBdYM zp0FM4zwMNEUwgfRzv1tEVVUEXmoFCyhzonUUw4nE4CFu/sE3ffhjKcXcY//qiSW xm4erY3XAgMBAAGjgZowgZcwCQYDVR0TBAIwADALBgNVHQ8EBAMCBLAwHQYDVR0O BBYEFO9t7XWuFf2SKLmuijgqR4sGDlRsMC4GA1UdEQQnMCWBI3NhbXVlbC53aWxs aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MC4GA1UdEgQnMCWBI3NhbXVlbC53aWxs aWFtc0BvcmlvbnRyYW5zZmVyLmNvLm56MA0GCSqGSIb3DQEBCwUAA4IBgQB5sxkE cBsSYwK6fYpM+hA5B5yZY2+L0Z+27jF1pWGgbhPH8/FjjBLVn+VFok3CDpRqwXCl xCO40JEkKdznNy2avOMra6PFiQyOE74kCtv7P+Fdc+FhgqI5lMon6tt9rNeXmnW/ c1NaMRdxy999hmRGzUSFjozcCwxpy/LwabxtdXwXgSay4mQ32EDjqR1TixS1+smp 8C/NCWgpIfzpHGJsjvmH2wAfKtTTqB9CVKLCWEnCHyCaRVuKkrKjqhYCdmMBqCws JkxfQWC+jBVeG9ZtPhQgZpfhvh+6hMhraUYRQ6XGyvBqEUe+yo6DKIT3MtGE2+CP eX9i9ZWBydWb8/rvmwmX2kkcBbX0hZS1rcR593hGc61JR6lvkGYQ2MYskBveyaxt Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8 voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg= -----END CERTIFICATE----- ruby-rspec-files-1.1.3/rspec-files.gemspec000066400000000000000000000013711432175712300204770ustar00rootroot00000000000000# frozen_string_literal: true require_relative "lib/rspec/files/version" Gem::Specification.new do |spec| spec.name = "rspec-files" spec.version = RSpec::Files::VERSION spec.summary = "RSpec helpers for buffering and detecting file descriptor leaks." spec.authors = ["Samuel Williams", "Scott Tadman", "Cyril Roelandt", "Gleb Sinyavskiy", "Olle Jonsson"] spec.license = "MIT" spec.cert_chain = ['release.cert'] spec.signing_key = File.expand_path('~/.gem/release.pem') spec.homepage = "https://github.com/socketry/rspec-files" spec.files = Dir.glob(['{lib}/**/*', '*.md'], File::FNM_DOTMATCH, base: __dir__) spec.add_dependency "rspec", "~> 3.0" spec.add_development_dependency "bundler" spec.add_development_dependency "covered" end ruby-rspec-files-1.1.3/spec/000077500000000000000000000000001432175712300156465ustar00rootroot00000000000000ruby-rspec-files-1.1.3/spec/rspec/000077500000000000000000000000001432175712300167625ustar00rootroot00000000000000ruby-rspec-files-1.1.3/spec/rspec/files/000077500000000000000000000000001432175712300200645ustar00rootroot00000000000000ruby-rspec-files-1.1.3/spec/rspec/files/buffer_spec.rb000066400000000000000000000005721432175712300227000ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019, by Samuel Williams. require 'rspec/files/buffer' RSpec.describe RSpec::Files::Buffer do include_context RSpec::Files::Buffer it "behaves like a file" do expect(buffer).to be_instance_of(File) end it "should not exist on disk" do expect(File).to_not be_exist(buffer.path) end end ruby-rspec-files-1.1.3/spec/rspec/files/leaks_spec.rb000066400000000000000000000016531432175712300225270ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019-2022, by Samuel Williams. # Copyright, 2020, by Scott Tadman. require 'rspec/files/leaks' require 'rspec/core/sandbox' require 'tempfile' RSpec.describe RSpec::Files::Leaks do include_context RSpec::Files::Leaks it "leaks IO instances" do expect(before_ios).to be == current_ios input, output = IO.pipe expect(before_ios).to_not be == current_ios input.close output.close expect(before_ios).to be == current_ios end it "fails if it leaks IO instances" do group = RSpec::Core::Sandbox.sandboxed{RSpec.describe} group.include_context RSpec::Files::Leaks pipe = nil group.example("leaky example") do pipe = IO.pipe end result = group.run pipe.each(&:close) expect(result).to be_falsy end it "shouldn't leak io" do # I've seen this create ios which are finalised. ok = `echo OK` end end ruby-rspec-files-1.1.3/spec/spec_helper.rb000066400000000000000000000006721432175712300204710ustar00rootroot00000000000000# frozen_string_literal: true # Released under the MIT License. # Copyright, 2019, by Samuel Williams. require 'covered/rspec' RSpec.configure do |config| # Enable flags like --only-failures and --next-failure config.example_status_persistence_file_path = ".rspec_status" # Disable RSpec exposing methods globally on `Module` and `main` config.disable_monkey_patching! config.expect_with :rspec do |c| c.syntax = :expect end end