pax_global_header00006660000000000000000000000064140744663220014522gustar00rootroot0000000000000052 comment=66f0ac85218d087b7cc4a60736f2bf8d761acc76 ruby-async-rspec-1.16.1/000077500000000000000000000000001407446632200150165ustar00rootroot00000000000000ruby-async-rspec-1.16.1/.editorconfig000066400000000000000000000000641407446632200174730ustar00rootroot00000000000000root = true [*] indent_style = tab indent_size = 2 ruby-async-rspec-1.16.1/.github/000077500000000000000000000000001407446632200163565ustar00rootroot00000000000000ruby-async-rspec-1.16.1/.github/workflows/000077500000000000000000000000001407446632200204135ustar00rootroot00000000000000ruby-async-rspec-1.16.1/.github/workflows/async-head.yml000066400000000000000000000007531407446632200231570ustar00rootroot00000000000000name: Async head on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu ruby: - head env: BUNDLE_GEMFILE: gems/async-head.rb steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 5 run: bundle exec rspec ruby-async-rspec-1.16.1/.github/workflows/async-v1.yml000066400000000000000000000007461407446632200226060ustar00rootroot00000000000000name: Async v1 on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest strategy: matrix: os: - ubuntu ruby: - 2.7 env: BUNDLE_GEMFILE: gems/async-v1.rb steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 5 run: bundle exec rspec ruby-async-rspec-1.16.1/.github/workflows/development.yml000066400000000000000000000015521407446632200234630ustar00rootroot00000000000000name: Development on: [push, pull_request] jobs: test: runs-on: ${{matrix.os}}-latest continue-on-error: ${{matrix.experimental}} strategy: matrix: os: - ubuntu - macos ruby: - 2.6 - 2.7 - "3.0" experimental: [false] env: [""] include: - os: ubuntu ruby: truffleruby experimental: true - os: ubuntu ruby: jruby experimental: true - os: ubuntu ruby: head experimental: true steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 with: ruby-version: ${{matrix.ruby}} bundler-cache: true - name: Run tests timeout-minutes: 5 run: ${{matrix.env}} bundle exec rspec ruby-async-rspec-1.16.1/.github/workflows/documentation.yml000066400000000000000000000011671407446632200240140ustar00rootroot00000000000000name: Documentation on: push: branches: - master jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: ruby/setup-ruby@v1 env: BUNDLE_WITH: maintenance with: ruby-version: 2.7 bundler-cache: true - name: Installing packages run: sudo apt-get install wget - name: Generate documentation timeout-minutes: 5 run: bundle exec bake utopia:project:static - name: Deploy documentation uses: JamesIves/github-pages-deploy-action@4.0.0 with: branch: docs folder: docs ruby-async-rspec-1.16.1/.gitignore000066400000000000000000000002121407446632200170010ustar00rootroot00000000000000/.bundle/ /.yardoc /gems.locked /_yardoc/ /coverage/ /doc/ /pkg/ /spec/reports/ /tmp/ # rspec failure tracking .rspec_status .covered.db ruby-async-rspec-1.16.1/.rspec000066400000000000000000000000701407446632200161300ustar00rootroot00000000000000--format documentation --warnings --require spec_helper ruby-async-rspec-1.16.1/README.md000066400000000000000000000071021407446632200162750ustar00rootroot00000000000000# Async::RSpec Provides useful `RSpec.shared_context`s for testing code that builds on top of [async](https://github.com/socketry/async). [![Development Status](https://github.com/socketry/async-rspec/workflows/Development/badge.svg)](https://github.com/socketry/async-rspec/actions?workflow=Development) ## Installation ``` shell $ bundle add async-rspec ``` Then add this require statement to the top of `spec/spec_helper.rb` ``` ruby require 'async/rspec' ``` ## Usage ### Async Reactor Many specs need to run within a reactor. A shared context is provided which includes all the relevant bits, including the above leaks checks. If your spec fails to run in less than 10 seconds, an `Async::TimeoutError` raises to prevent your test suite from hanging. ``` ruby require 'async/io' RSpec.describe Async::IO do include_context Async::RSpec::Reactor let(:pipe) {IO.pipe} let(:input) {Async::IO::Generic.new(pipe.first)} let(:output) {Async::IO::Generic.new(pipe.last)} it "should send and receive data within the same reactor" do message = nil output_task = reactor.async do message = input.read(1024) end reactor.async do output.write("Hello World") end output_task.wait expect(message).to be == "Hello World" input.close output.close end end ``` ### Changing Timeout You can change the timeout by specifying it as an option: ``` ruby RSpec.describe MySlowThing, timeout: 60 do # ... end ``` ### File Descriptor Leaks Leaking sockets and other kinds of IOs are a problem for long running services. `Async::RSpec::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 Async::RSpec::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. ### Allocations This functionality was moved to [`rspec-memory`](https://github.com/socketry/rspec-memory). ## 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 ## License Released under the MIT license. Copyright, 2017, by [Samuel G. D. Williams](http://www.codeotaku.com/samuel-williams). 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-async-rspec-1.16.1/async-rspec.gemspec000066400000000000000000000013121407446632200206070ustar00rootroot00000000000000 require_relative "lib/async/rspec/version" Gem::Specification.new do |spec| spec.name = "async-rspec" spec.version = Async::RSpec::VERSION spec.summary = "Helpers for writing specs against the async gem." spec.authors = ["Samuel Williams"] spec.license = "MIT" spec.homepage = "https://github.com/socketry/async-rspec" spec.files = Dir.glob('{lib}/**/*', File::FNM_DOTMATCH, base: __dir__) spec.add_dependency "rspec", "~> 3.0" spec.add_dependency "rspec-files", "~> 1.0" spec.add_dependency "rspec-memory", "~> 1.0" spec.add_development_dependency "async" spec.add_development_dependency "async-io" spec.add_development_dependency "bundler" spec.add_development_dependency "covered" end ruby-async-rspec-1.16.1/gems.rb000066400000000000000000000004521407446632200162770ustar00rootroot00000000000000source 'https://rubygems.org' # Specify your gem's dependencies in async-rspec.gemspec gemspec # gem "async", path: "../async" group :maintenance, optional: true do gem "bake-modernize" gem "bake-bundler" end group :test do gem "ruby-prof", git: "https://github.com/ruby-prof/ruby-prof" end ruby-async-rspec-1.16.1/gems/000077500000000000000000000000001407446632200157515ustar00rootroot00000000000000ruby-async-rspec-1.16.1/gems/async-head.rb000066400000000000000000000002111407446632200203040ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec path: "../" gem 'async', git: "https://github.com/socketry/async" ruby-async-rspec-1.16.1/gems/async-v1.rb000066400000000000000000000001511407446632200177340ustar00rootroot00000000000000# frozen_string_literal: true source 'https://rubygems.org' gemspec path: "../" gem 'async', '~> 1.0' ruby-async-rspec-1.16.1/lib/000077500000000000000000000000001407446632200155645ustar00rootroot00000000000000ruby-async-rspec-1.16.1/lib/async/000077500000000000000000000000001407446632200167015ustar00rootroot00000000000000ruby-async-rspec-1.16.1/lib/async/rspec.rb000066400000000000000000000023171407446632200203450ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require_relative "rspec/version" require_relative "rspec/reactor" require_relative "rspec/memory" ruby-async-rspec-1.16.1/lib/async/rspec/000077500000000000000000000000001407446632200200155ustar00rootroot00000000000000ruby-async-rspec-1.16.1/lib/async/rspec/buffer.rb000066400000000000000000000031041407446632200216110ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # 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. require 'securerandom' module Async module RSpec 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-async-rspec-1.16.1/lib/async/rspec/leaks.rb000066400000000000000000000023101407446632200214350ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require 'rspec/files' module Async module RSpec Leaks = ::RSpec::Files::Leaks end end ruby-async-rspec-1.16.1/lib/async/rspec/memory.rb000066400000000000000000000023041407446632200216510ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require 'rspec/memory' module Async module RSpec Memory = ::RSpec::Memory end end ruby-async-rspec-1.16.1/lib/async/rspec/profile.rb000066400000000000000000000032441407446632200220050ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. module Async module RSpec module Profile end begin require 'ruby-prof' ::RSpec.shared_context Profile do around(:each) do |example| profile = RubyProf::Profile.new(merge_fibers: true) begin profile.start example.run ensure profile.stop printer = RubyProf::FlatPrinter.new(profile) printer.print(STDOUT) end end end rescue LoadError ::RSpec.shared_context Profile do before(:all) do warn "Profiling not enabled/supported." end end end end end ruby-async-rspec-1.16.1/lib/async/rspec/reactor.rb000066400000000000000000000055201407446632200220030ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require_relative 'leaks' require 'kernel/sync' require 'kernel/async' require 'async/reactor' require 'async/task' module Async module RSpec module Reactor def notify_failure(exception = $!) ::RSpec::Support.notify_failure(exception) end def run_in_reactor(reactor, duration = nil) result = nil timer_task = nil if duration timer_task = reactor.async do |task| # Wait for the timeout, at any point this task might be cancelled if the user code completes: task.annotate("Timer task duration=#{duration}.") task.sleep(duration) # The timeout expired, so generate an error: buffer = StringIO.new reactor.print_hierarchy(buffer) # Raise an error so it is logged: raise TimeoutError, "Run time exceeded duration #{duration}s:\n#{buffer.string}" end end spec_task = reactor.async do |spec_task| spec_task.annotate("running example") result = yield(spec_task) # We are finished, so stop the timer task if it was started: timer_task&.stop # Now stop the entire reactor: raise Async::Stop end begin timer_task&.wait spec_task.wait ensure spec_task.stop end return result end end ::RSpec.shared_context Reactor do include Reactor let(:reactor) {@reactor} include_context Async::RSpec::Leaks around(:each) do |example| duration = example.metadata.fetch(:timeout, 10) begin Sync do |task| @reactor = task.reactor task.annotate(self.class) run_in_reactor(@reactor, duration) do example.run end ensure @reactor = nil end end end end end end ruby-async-rspec-1.16.1/lib/async/rspec/ssl.rb000066400000000000000000000173331407446632200211520ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # 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. require 'openssl' module Async module RSpec module SSL module CertificateAuthority end module ValidCertificate end module InvalidCertificate end module VerifiedContexts end module HostCertificates end end ::RSpec.shared_context SSL::CertificateAuthority do # This key size is generally considered insecure, but it's fine for testing. let(:certificate_authority_key) {OpenSSL::PKey::RSA.new(2048)} let(:certificate_authority_name) {OpenSSL::X509::Name.parse("O=TestCA/CN=localhost")} # The certificate authority is used for signing and validating the certificate which is used for communciation: let(:certificate_authority) do certificate = OpenSSL::X509::Certificate.new certificate.subject = certificate_authority_name # We use the same issuer as the subject, which makes this certificate self-signed: certificate.issuer = certificate_authority_name certificate.public_key = certificate_authority_key.public_key certificate.serial = 1 certificate.version = 2 certificate.not_before = Time.now certificate.not_after = Time.now + 3600 extension_factory = OpenSSL::X509::ExtensionFactory.new extension_factory.subject_certificate = certificate extension_factory.issuer_certificate = certificate certificate.add_extension extension_factory.create_extension("basicConstraints", "CA:TRUE", true) certificate.add_extension extension_factory.create_extension("keyUsage", "keyCertSign, cRLSign", true) certificate.add_extension extension_factory.create_extension("subjectKeyIdentifier", "hash") certificate.add_extension extension_factory.create_extension("authorityKeyIdentifier", "keyid:always", false) certificate.sign certificate_authority_key, OpenSSL::Digest::SHA256.new end let(:certificate_store) do # The certificate store which is used for validating the server certificate: OpenSSL::X509::Store.new.tap do |certificates| certificates.add_cert(certificate_authority) end end end ::RSpec.shared_context SSL::ValidCertificate do include_context SSL::CertificateAuthority # The private key to use on the server side: let(:key) {OpenSSL::PKey::RSA.new(2048)} let(:certificate_name) {OpenSSL::X509::Name.parse("O=Test/CN=localhost")} # The certificate used for actual communication: let(:certificate) do certificate = OpenSSL::X509::Certificate.new certificate.subject = certificate_name certificate.issuer = certificate_authority.subject certificate.public_key = key.public_key certificate.serial = 2 certificate.version = 2 certificate.not_before = Time.now certificate.not_after = Time.now + 3600 extension_factory = OpenSSL::X509::ExtensionFactory.new() extension_factory.subject_certificate = certificate extension_factory.issuer_certificate = certificate_authority certificate.add_extension extension_factory.create_extension("keyUsage", "digitalSignature", true) certificate.add_extension extension_factory.create_extension("subjectKeyIdentifier", "hash") certificate.sign certificate_authority_key, OpenSSL::Digest::SHA256.new end end ::RSpec.shared_context SSL::HostCertificates do include_context SSL::CertificateAuthority let(:keys) do Hash[ hosts.collect{|name| [name, OpenSSL::PKey::RSA.new(2048)]} ] end # The certificate used for actual communication: let(:certificates) do Hash[ hosts.collect do |name| certificate_name = OpenSSL::X509::Name.parse("O=Test/CN=#{name}") certificate = OpenSSL::X509::Certificate.new certificate.subject = certificate_name certificate.issuer = certificate_authority.subject certificate.public_key = keys[name].public_key certificate.serial = 2 certificate.version = 2 certificate.not_before = Time.now certificate.not_after = Time.now + 3600 extension_factory = OpenSSL::X509::ExtensionFactory.new extension_factory.subject_certificate = certificate extension_factory.issuer_certificate = certificate_authority certificate.add_extension extension_factory.create_extension("keyUsage", "digitalSignature", true) certificate.add_extension extension_factory.create_extension("subjectKeyIdentifier", "hash") certificate.sign certificate_authority_key, OpenSSL::Digest::SHA256.new [name, certificate] end ] end let(:server_context) do OpenSSL::SSL::SSLContext.new.tap do |context| context.servername_cb = Proc.new do |socket, name| if hosts.include? name socket.hostname = name OpenSSL::SSL::SSLContext.new.tap do |context| context.cert = certificates[name] context.key = keys[name] end end end end end let(:client_context) do OpenSSL::SSL::SSLContext.new.tap do |context| context.cert_store = certificate_store context.verify_mode = OpenSSL::SSL::VERIFY_PEER end end end ::RSpec.shared_context SSL::InvalidCertificate do include_context SSL::CertificateAuthority # The private key to use on the server side: let(:key) {OpenSSL::PKey::RSA.new(2048)} let(:invalid_key) {OpenSSL::PKey::RSA.new(2048)} let(:certificate_name) {OpenSSL::X509::Name.parse("O=Test/CN=localhost")} # The certificate used for actual communication: let(:certificate) do certificate = OpenSSL::X509::Certificate.new certificate.subject = certificate_name certificate.issuer = certificate_authority.subject certificate.public_key = key.public_key certificate.serial = 2 certificate.version = 2 certificate.not_before = Time.now - 3600 certificate.not_after = Time.now extension_factory = OpenSSL::X509::ExtensionFactory.new() extension_factory.subject_certificate = certificate extension_factory.issuer_certificate = certificate_authority certificate.add_extension extension_factory.create_extension("keyUsage", "digitalSignature", true) certificate.add_extension extension_factory.create_extension("subjectKeyIdentifier", "hash") certificate.sign invalid_key, OpenSSL::Digest::SHA256.new end end ::RSpec.shared_context SSL::VerifiedContexts do let(:server_context) do OpenSSL::SSL::SSLContext.new.tap do |context| context.cert = certificate context.key = key end end let(:client_context) do OpenSSL::SSL::SSLContext.new.tap do |context| context.cert_store = certificate_store context.verify_mode = OpenSSL::SSL::VERIFY_PEER end end end end end ruby-async-rspec-1.16.1/lib/async/rspec/version.rb000066400000000000000000000022461407446632200220330ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. module Async module RSpec VERSION = "1.16.1" end end ruby-async-rspec-1.16.1/spec/000077500000000000000000000000001407446632200157505ustar00rootroot00000000000000ruby-async-rspec-1.16.1/spec/async/000077500000000000000000000000001407446632200170655ustar00rootroot00000000000000ruby-async-rspec-1.16.1/spec/async/rspec/000077500000000000000000000000001407446632200202015ustar00rootroot00000000000000ruby-async-rspec-1.16.1/spec/async/rspec/buffer_spec.rb000066400000000000000000000025761407446632200230230ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # 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. require 'async/rspec/buffer' RSpec.describe Async::RSpec::Buffer do include_context Async::RSpec::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-async-rspec-1.16.1/spec/async/rspec/leaks_spec.rb000066400000000000000000000026631407446632200226460ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require 'async/rspec/leaks' RSpec.describe "leaks context" do include_context Async::RSpec::Leaks it "leaks io" 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 end ruby-async-rspec-1.16.1/spec/async/rspec/memory_spec.rb000066400000000000000000000060521407446632200230530ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require 'async/rspec/memory' RSpec.describe Async::RSpec::Memory do include_context Async::RSpec::Memory it "should execute code in block" do string = nil expect do string = String.new end.to limit_allocations(String => 1) expect(string).to_not be_nil end context "on supported platform", if: Async::RSpec::Memory::Trace.supported? do it "should not exceed specified count limit" do expect do 2.times{String.new} end.to limit_allocations(String => 2) expect do 2.times{String.new} end.to limit_allocations.of(String, count: 2) end it "should fail if there are untracked allocations" do expect do expect do Array.new end.to limit_allocations end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /it was not specified/) end it "should exceed specified count limit" do expect do expect do 6.times{String.new} end.to limit_allocations(String => 4) end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected exactly 4 instances/) end if Async::RSpec::Memory::Trace.supported? it "should be within specified count range" do expect do 2.times{String.new} end.to limit_allocations(String => 1..3) expect do 2.times{String.new} end.to limit_allocations.of(String, count: 1..3) end it "should exceed specified count range" do expect do expect do 6.times{String.new} end.to limit_allocations(String => 1..3) end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected within 1..3 instances/) end it "should not exceed specified size limit" do expect do "a" * 100_000 end.to limit_allocations.of(String, size: 100_001) end it "should exceed specified size limit" do expect do expect do "a" * 120_000 end.to limit_allocations(size: 100_000) end.to raise_error(RSpec::Expectations::ExpectationNotMetError, /expected exactly 100000 bytes/) end end end ruby-async-rspec-1.16.1/spec/async/rspec/profile_spec.rb000066400000000000000000000025421407446632200232030ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require 'async' require 'async/rspec/profile' RSpec.describe Async::RSpec::Profile do include_context Async::RSpec::Profile it "profiles the function" do Async do |parent| Async do |child| child.sleep(1) end.wait end end end ruby-async-rspec-1.16.1/spec/async/rspec/reactor_spec.rb000066400000000000000000000045371407446632200232100ustar00rootroot00000000000000# Copyright, 2017, by Samuel G. D. Williams. # # 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. require 'async/rspec/reactor' require 'async/io/generic' RSpec.describe Async::RSpec::Reactor do context "with shared context", timeout: 1 do include_context Async::RSpec::Reactor # The following fails: it "has reactor" do expect(reactor).to be_kind_of Async::Reactor end it "doesn't time out" do reactor.async do |task| expect do task.sleep(0.1) end.to_not raise_error end.wait end # it "times out" do # reactor.async do |task| # task.sleep(2) # end.wait # end # # it "propagates errors" do # reactor.async do |task| # raise "Boom!" # end.wait # end end context "timeouts", timeout: 1 do include Async::RSpec::Reactor it "times out" do expect do Sync do |task| run_in_reactor(task.reactor, 0.05) do |spec_task| spec_task.sleep(0.1) end end end.to raise_error(Async::TimeoutError) end it "doesn't time out" do expect do Sync do |task| run_in_reactor(task.reactor, 0.05) do |spec_task| spec_task.sleep(0.01) end end end.to_not raise_error end # it "propagates errors" do # expect do # run_in_reactor(reactor, 0.05) do # raise "Boom!" # end # end.to raise_error("Boom!") # end end end ruby-async-rspec-1.16.1/spec/async/rspec/ssl_spec.rb000066400000000000000000000035461407446632200223510ustar00rootroot00000000000000# Copyright, 2018, by Samuel G. D. Williams. # # 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. require 'async/rspec/ssl' RSpec.describe Async::RSpec::SSL do context Async::RSpec::SSL::CertificateAuthority do include_context Async::RSpec::SSL::CertificateAuthority it "has a valid certificate authority" do expect(certificate_authority.verify(certificate_authority_key)).to be_truthy end end context Async::RSpec::SSL::ValidCertificate do include_context Async::RSpec::SSL::ValidCertificate it "can validate client certificate" do expect(certificate_store.verify(certificate)).to be_truthy end end context Async::RSpec::SSL::InvalidCertificate do include_context Async::RSpec::SSL::InvalidCertificate it "fails to validate certificate" do expect(certificate_store.verify(certificate)).to be_falsey end end end ruby-async-rspec-1.16.1/spec/spec_helper.rb000066400000000000000000000005221407446632200205650ustar00rootroot00000000000000 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