diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c439cb4..65b1c72d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,16 +25,10 @@ jobs: strategy: fail-fast: false matrix: - ruby: - - 2.6 - - 2.7 - - "3.0" - - 3.1 - - ruby-head - - jruby + ruby: [2.6, 2.7, '3.0', 3.1, 3.2, ruby-head, jruby] steps: - name: Clone repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: @@ -54,7 +48,7 @@ jobs: runs-on: windows-latest env: CI: true - ALLOW_FAILURES: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'jruby' }} + ALLOW_FAILURES: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'jruby' || matrix.ruby == '3.1' }} strategy: fail-fast: false matrix: @@ -62,7 +56,7 @@ jobs: - 3.1 steps: - name: Clone repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml index 40a1cfce..d01bae11 100644 --- a/.github/workflows/generate-docs.yml +++ b/.github/workflows/generate-docs.yml @@ -10,7 +10,7 @@ jobs: name: Update gh-pages with docs steps: - name: Clone repository - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Set up Ruby uses: ruby/setup-ruby@v1 with: diff --git a/VERSION b/VERSION index e650c01d..f15386a5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.9 +3.2.10 diff --git a/lib/rdf/mixin/mutable.rb b/lib/rdf/mixin/mutable.rb index 1f7c8ea3..4547e366 100644 --- a/lib/rdf/mixin/mutable.rb +++ b/lib/rdf/mixin/mutable.rb @@ -41,7 +41,7 @@ def immutable? def load(url, graph_name: nil, **options) raise TypeError.new("#{self} is immutable") if immutable? - Reader.open(url, base_uri: url, **options) do |reader| + Reader.open(url, **options.merge(base_uri: url)) do |reader| if graph_name statements = [] reader.each_statement do |statement| diff --git a/lib/rdf/ntriples/writer.rb b/lib/rdf/ntriples/writer.rb index f9793c50..c155bd74 100644 --- a/lib/rdf/ntriples/writer.rb +++ b/lib/rdf/ntriples/writer.rb @@ -125,16 +125,18 @@ def self.escape_unicode(u, encoding) # @see http://www.w3.org/TR/n-triples/ def self.escape_ascii(u, encoding) case (u = u.ord) - when (0x00..0x07) then escape_utf16(u) - when (0x0A) then "\\n" - when (0x0D) then "\\r" - when (0x0E..0x1F) then escape_utf16(u) - when (0x22) then "\\\"" - when (0x5C) then "\\\\" - when (0x7F) then escape_utf16(u) - when (0x00..0x7F) then u.chr - else - raise ArgumentError.new("expected an ASCII character in (0x00..0x7F), but got 0x#{u.to_s(16)}") + when (0x08) then "\\b" + when (0x09) then "\\t" + when (0x0A) then "\\n" + when (0x0C) then "\\f" + when (0x0D) then "\\r" + when (0x22) then "\\\"" + when (0x5C) then "\\\\" + when (0x00..0x1F) then escape_utf16(u) + when (0x7F) then escape_utf16(u) + when (0x20..0x7E) then u.chr + else + raise ArgumentError.new("expected an ASCII character in (0x00..0x7F), but got 0x#{u.to_s(16)}") end end diff --git a/lib/rdf/util/cache.rb b/lib/rdf/util/cache.rb index 7c2e25b3..56fd5598 100644 --- a/lib/rdf/util/cache.rb +++ b/lib/rdf/util/cache.rb @@ -85,7 +85,7 @@ def []=(key, value) id = value.__id__ @cache[key] = id @index[id] = key - ObjectSpace.define_finalizer(value, proc {|id| @cache.delete(@index.delete(id))}) + ObjectSpace.define_finalizer(value, finalizer_proc) end value end @@ -100,6 +100,12 @@ def delete(key) @cache.delete(key) @index.delete(id) if id end + + private + + def finalizer_proc + proc { |id| @cache.delete(@index.delete(id)) } + end end # ObjectSpaceCache ## diff --git a/lib/rdf/util/logger.rb b/lib/rdf/util/logger.rb index f5208bee..68ed2902 100644 --- a/lib/rdf/util/logger.rb +++ b/lib/rdf/util/logger.rb @@ -181,10 +181,10 @@ def log_debug(*args, level: :debug, **options, &block) end ## - # @overload log_depth(options, &block) + # @overload log_depth(depth: 1, **options, &block) # Increase depth around a method invocation + # @param [Integer] :depth Additional recursion depth # @param [Hash{Symbol}] options (@options || {}) - # @option options [Integer] :depth Additional recursion depth # @option options [Logger, #<<] :logger # @yield # Yields with no arguments @@ -194,8 +194,8 @@ def log_debug(*args, level: :debug, **options, &block) # @overload log_depth # # Return the current log depth # @return [Integer] - def log_depth(**options, &block) - self.logger(**options).log_depth(&block) + def log_depth(depth: 1, **options, &block) + self.logger(**options).log_depth(depth: depth, &block) end private @@ -244,7 +244,7 @@ def log_statistics end ## - # @overload log_depth(options, &block) + # @overload log_depth(depth: 1, **options, &block) # Increase depth around a method invocation # @param [Integer] depth (1) recursion depth # @param [Hash{Symbol}] options (@options || {}) diff --git a/rdf.gemspec b/rdf.gemspec index 99318e1a..a6f3daf9 100755 --- a/rdf.gemspec +++ b/rdf.gemspec @@ -35,11 +35,11 @@ Gem::Specification.new do |gem| gem.add_development_dependency 'rdf-vocab', '~> 3.2' gem.add_development_dependency 'rdf-xsd', '~> 3.2', '>= 3.2.1' gem.add_development_dependency 'rest-client', '~> 2.1' - gem.add_development_dependency 'rspec', '~> 3.10' + gem.add_development_dependency 'rspec', '~> 3.12' gem.add_development_dependency 'rspec-its', '~> 1.3' - gem.add_development_dependency 'webmock', '~> 3.14' + gem.add_development_dependency 'webmock', '~> 3.18' gem.add_development_dependency 'yard', '~> 0.9' - gem.add_development_dependency 'faraday', '~> 1.8' + gem.add_development_dependency 'faraday', '~> 1.10' gem.add_development_dependency 'faraday_middleware', '~> 1.2' gem.post_install_message = nil diff --git a/spec/ntriples_spec.rb b/spec/ntriples_spec.rb index c71e601c..1622cdf1 100644 --- a/spec/ntriples_spec.rb +++ b/spec/ntriples_spec.rb @@ -573,7 +573,7 @@ end end - context "Writing a Statements" do + context "Writing Statements" do let(:statements) {[ RDF::Statement(RDF::URI('s'), RDF::URI('p'), RDF::URI('o1')), RDF::Statement(RDF::URI('s'), RDF::URI('p'), RDF::URI('o2')) @@ -600,6 +600,10 @@ expect(writer.new.format_literal(RDF::Literal.new('Hello, world!'))).to eq '"Hello, world!"' end + it "should correctly format string literals" do + expect(writer.new.format_literal(RDF::Literal.new('Hello, world!', datatype: RDF::XSD.string))).to eq '"Hello, world!"' + end + it "should correctly format language-tagged literals" do expect(writer.new.format_literal(RDF::Literal.new('Hello, world!', language: :en))).to eq '"Hello, world!"@en' end @@ -848,11 +852,11 @@ # @see http://www.w3.org/TR/rdf-testcases/#ntrip_strings it "should correctly escape ASCII characters (#x0-#x7F)" do (0x00..0x07).each { |u| expect(writer.escape(u.chr, encoding)).to eq "\\u#{u.to_s(16).upcase.rjust(4, '0')}" } - expect(writer.escape(0x08.chr, encoding)).to eq "\b" - expect(writer.escape(0x09.chr, encoding)).to eq "\t" + expect(writer.escape(0x08.chr, encoding)).to eq "\\b" + expect(writer.escape(0x09.chr, encoding)).to eq "\\t" expect(writer.escape(0x0A.chr, encoding)).to eq "\\n" - expect(writer.escape(0x0B.chr, encoding)).to eq "\v" - expect(writer.escape(0x0C.chr, encoding)).to eq "\f" + expect(writer.escape(0x0B.chr, encoding)).to eq "\\u000B" + expect(writer.escape(0x0C.chr, encoding)).to eq "\\f" expect(writer.escape(0x0D.chr, encoding)).to eq "\\r" (0x0E..0x1F).each { |u| expect(writer.escape(u.chr, encoding)).to eq "\\u#{u.to_s(16).upcase.rjust(4, '0')}" } (0x20..0x21).each { |u| expect(writer.escape(u.chr, encoding)).to eq u.chr } @@ -910,11 +914,11 @@ # @see http://www.w3.org/TR/rdf-testcases/#ntrip_strings it "should correctly escape ASCII characters (#x0-#x7F)" do (0x00..0x07).each { |u| expect(writer.escape(u.chr, encoding)).to eq "\\u#{u.to_s(16).upcase.rjust(4, '0')}" } - expect(writer.escape(0x08.chr, encoding)).to eq "\b" - expect(writer.escape(0x09.chr, encoding)).to eq "\t" + expect(writer.escape(0x08.chr, encoding)).to eq "\\b" + expect(writer.escape(0x09.chr, encoding)).to eq "\\t" expect(writer.escape(0x0A.chr, encoding)).to eq "\\n" - expect(writer.escape(0x0B.chr, encoding)).to eq "\v" - expect(writer.escape(0x0C.chr, encoding)).to eq "\f" + expect(writer.escape(0x0B.chr, encoding)).to eq "\\u000B" + expect(writer.escape(0x0C.chr, encoding)).to eq "\\f" expect(writer.escape(0x0D.chr, encoding)).to eq "\\r" (0x0E..0x1F).each { |u| expect(writer.escape(u.chr, encoding)).to eq "\\u#{u.to_s(16).upcase.rjust(4, '0')}" } (0x20..0x21).each { |u| expect(writer.escape(u.chr, encoding)).to eq u.chr } diff --git a/spec/util/cache_spec.rb b/spec/util/cache_spec.rb new file mode 100644 index 00000000..c22a521e --- /dev/null +++ b/spec/util/cache_spec.rb @@ -0,0 +1,80 @@ +require_relative '../spec_helper' + +describe RDF::Util::Cache do + subject(:cache) do + described_class.new(10) + end + + describe '#capacity' do + it 'returns the cache size' do + expect(cache.capacity).to eq 10 + end + end + + describe '#size' do + it 'returns the cache size' do + cache[:key] = {} + expect(cache.size).to eq 1 + end + end + + describe '#[]' do + it 'returns the value' do + cache[:key] = {} + expect(cache[:key]).to eq({}) + end + end + + describe '#[]=' do + context 'when the cache is not full' do + it 'stores the value' do + expect { + cache[:key] = {} + }.to change(cache, :size).by(1) + end + + it 'returns the value' do + expect(cache[:key] = {}).to eq({}) + end + end + + context 'when the cache is full' do + before do + 10.times { |i| cache[i] = {} } + end + + it 'does not store the value' do + expect { + cache[:key] = {} + }.not_to change(cache, :size) + end + + it 'returns the value' do + expect(cache[:key] = {}).to eq({}) + end + end + end + + context 'when the GC starts' do + before do + 100.times { |i| cache[i] = {}; nil } + end + + # Sometimes the last reference is not gc + it 'cleans the unused references' do + expect { + GC.start + }.to change(cache, :size).by_at_most(-9) + end + end + + describe '#delete' do + before do + cache[:key] = {} + end + + it 'delete the value' do + expect { cache.delete(:key) }.to change(cache, :size).to(0) + end + end +end \ No newline at end of file diff --git a/spec/vocabulary_spec.rb b/spec/vocabulary_spec.rb index d8e63592..3c096c6b 100644 --- a/spec/vocabulary_spec.rb +++ b/spec/vocabulary_spec.rb @@ -462,8 +462,7 @@ describe ".imports" do { - RDF::Vocab::FOAF => [], - RDF::Vocab::WOT => [RDF::RDFS, RDF::OWL] + RDF::Vocab::FOAF => [] }.each do |v, r| context v.to_uri do subject {v} @@ -476,8 +475,7 @@ describe ".imported_from" do { - RDF::RDFS => [RDF::OWL, RDF::Vocab::WOT], - RDF::OWL => [RDF::Vocab::WOT] + RDF::RDFS => [RDF::OWL], }.each do |v, r| context v.to_uri do subject {v}