main
1# frozen_string_literal: true
2
3RSpec.describe Saml::Kit::XsdValidatable do
4 let(:metadata_xml) do
5 Saml::Kit::IdentityProviderMetadata.build do |x|
6 x.entity_id = 'https://idp.example.com/metadata'
7 x.add_single_sign_on_service(
8 'https://idp.example.com/login', binding: :http_post
9 )
10 end.to_xml
11 end
12
13 let(:request_xml) do
14 Saml::Kit::AuthenticationRequest.build do |x|
15 x.issuer = 'https://sp.example.com/metadata'
16 end.to_xml
17 end
18
19 describe 'concurrent validation' do
20 # Compiling the schema inside Dir.chdir mutated process global state, and
21 # ruby raises when one thread enters a chdir block while another is inside
22 # one, so this raised "conflicting chdir during another chdir block".
23 it 'does not raise when many threads validate at once' do
24 threads = 8.times.map do
25 Thread.new do
26 20.times do
27 Saml::Kit::IdentityProviderMetadata.new(metadata_xml).valid?
28 Saml::Kit::AuthenticationRequest.new(request_xml).valid?
29 end
30 end
31 end
32 expect { threads.each(&:value) }.not_to raise_error
33 end
34
35 it 'reports the same result in every thread' do
36 threads = 8.times.map do
37 Thread.new { Saml::Kit::IdentityProviderMetadata.new(metadata_xml).valid? }
38 end
39 expect(threads.map(&:value).uniq).to eql([true])
40 end
41 end
42
43 describe 'schema resolution' do
44 # Our xsds import each other by relative filename, so this fails if they
45 # ever resolve against the working directory instead of the xsd's own.
46 it 'validates from an unrelated working directory' do
47 Dir.chdir('/') do
48 expect(Saml::Kit::IdentityProviderMetadata.new(metadata_xml)).to be_valid
49 end
50 end
51 end
52
53 describe 'schema compilation' do
54 around do |example|
55 cached = described_class.instance_variable_get(:@schemas)
56 described_class.instance_variable_set(:@schemas, {})
57 example.run
58 described_class.instance_variable_set(:@schemas, cached)
59 end
60
61 it 'compiles a schema once however often it is validated' do
62 allow(Nokogiri::XML::Schema).to receive(:from_document).and_call_original
63 3.times { Saml::Kit::IdentityProviderMetadata.new(metadata_xml).valid? }
64 expect(Nokogiri::XML::Schema).to have_received(:from_document).once
65 end
66 end
67end