diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 65b1c72d..583871d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,7 +38,7 @@ jobs: - name: Run tests run: ruby --version; bundle exec rspec spec || $ALLOW_FAILURES - name: Coveralls GitHub Action - uses: coverallsapp/github-action@v1.1.2 + uses: coverallsapp/github-action@v2 if: "matrix.ruby == '3.0'" with: github-token: ${{ secrets.GITHUB_TOKEN }} @@ -66,7 +66,7 @@ jobs: - name: Run tests run: ruby --version; bundle exec rspec spec || $ALLOW_FAILURES - name: Coveralls GitHub Action - uses: coverallsapp/github-action@v1.1.2 + uses: coverallsapp/github-action@v2 if: "matrix.ruby == '3.0'" with: github-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 8f656ee1..9313d87a 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This is a pure-Ruby library for working with [Resource Description Framework * -[![Gem Version](https://badge.fury.io/rb/rdf.png)](https://badge.fury.io/rb/rdf) +[![Gem Version](https://badge.fury.io/rb/rdf.svg)](https://badge.fury.io/rb/rdf) [![Build Status](https://github.com/ruby-rdf/rdf/workflows/CI/badge.svg?branch=develop)](https://github.com/ruby-rdf/rdf/actions?query=workflow%3ACI) [![Coverage Status](https://coveralls.io/repos/ruby-rdf/rdf/badge.svg?branch=develop)](https://coveralls.io/github/ruby-rdf/rdf?branch=develop) [![Gitter chat](https://badges.gitter.im/ruby-rdf/rdf.png)](https://gitter.im/ruby-rdf/rdf) diff --git a/VERSION b/VERSION index f15386a5..17ce9180 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.2.10 +3.2.11 diff --git a/lib/rdf.rb b/lib/rdf.rb index b16ec0c6..6e034773 100644 --- a/lib/rdf.rb +++ b/lib/rdf.rb @@ -5,7 +5,6 @@ require "ostruct" require 'rdf/version' -require 'rdf/extensions' module RDF # RDF mixins diff --git a/lib/rdf/extensions.rb b/lib/rdf/extensions.rb deleted file mode 100644 index e77631a0..00000000 --- a/lib/rdf/extensions.rb +++ /dev/null @@ -1,22 +0,0 @@ -## -# This file provides compatibility monkeypatches to standard library classes -# Implementation taken from MIT-licensed https://github.com/marcandre/backports -# - -# https://github.com/marcandre/backports/blob/master/lib/backports/2.4.0/regexp/match.rb -unless Regexp.method_defined? :match? - class Regexp - def match?(*args) - !match(*args).nil? - end - end -end - -# https://github.com/marcandre/backports/blob/master/lib/backports/2.4.0/string/match.rb -unless String.method_defined? :match? - class String - def match?(*args) - !match(*args).nil? - end - end -end diff --git a/lib/rdf/model/list.rb b/lib/rdf/model/list.rb index 7607b63e..c7e85b9a 100644 --- a/lib/rdf/model/list.rb +++ b/lib/rdf/model/list.rb @@ -280,19 +280,6 @@ def *(int_or_str) end end - ## - # Returns the element at `index`. - # - # @example - # RDF::List[1, 2, 3][0] #=> RDF::Literal(1) - # - # @param [Integer] index - # @return [RDF::Term] - # @see http://ruby-doc.org/core-2.2.2/Array.html#method-i-5B-5D - def [](index) - at(index) - end - ## # Element Assignment — Sets the element at `index`, or replaces a subarray from the `start` index for `length` elements, or replaces a subarray specified by the `range` of indices. # diff --git a/lib/rdf/model/uri.rb b/lib/rdf/model/uri.rb index 9de45e68..e6deb7aa 100644 --- a/lib/rdf/model/uri.rb +++ b/lib/rdf/model/uri.rb @@ -1,4 +1,5 @@ # coding: utf-8 +# frozen_string_literal: true require 'cgi' module RDF @@ -28,27 +29,27 @@ class URI include RDF::Resource # IRI components - UCSCHAR = Regexp.compile(<<-EOS.gsub(/\s+/, '')) - [\\u00A0-\\uD7FF]|[\\uF900-\\uFDCF]|[\\uFDF0-\\uFFEF]| - [\\u{10000}-\\u{1FFFD}]|[\\u{20000}-\\u{2FFFD}]|[\\u{30000}-\\u{3FFFD}]| - [\\u{40000}-\\u{4FFFD}]|[\\u{50000}-\\u{5FFFD}]|[\\u{60000}-\\u{6FFFD}]| - [\\u{70000}-\\u{7FFFD}]|[\\u{80000}-\\u{8FFFD}]|[\\u{90000}-\\u{9FFFD}]| - [\\u{A0000}-\\u{AFFFD}]|[\\u{B0000}-\\u{BFFFD}]|[\\u{C0000}-\\u{CFFFD}]| - [\\u{D0000}-\\u{DFFFD}]|[\\u{E1000}-\\u{EFFFD}] - EOS - IPRIVATE = Regexp.compile("[\\uE000-\\uF8FF]|[\\u{F0000}-\\u{FFFFD}]|[\\u100000-\\u10FFFD]").freeze + UCSCHAR = %( + \\u00A0-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFEF + \\u{10000}-\\u{1FFFD}\\u{20000}-\\u{2FFFD}\\u{30000}-\\u{3FFFD} + \\u{40000}-\\u{4FFFD}\\u{50000}-\\u{5FFFD}\\u{60000}-\\u{6FFFD} + \\u{70000}-\\u{7FFFD}\\u{80000}-\\u{8FFFD}\\u{90000}-\\u{9FFFD} + \\u{A0000}-\\u{AFFFD}\\u{B0000}-\\u{BFFFD}\\u{C0000}-\\u{CFFFD} + \\u{D0000}-\\u{DFFFD}\\u{E1000}-\\u{EFFFD} + ).gsub(/\s+/, '') + IPRIVATE = Regexp.compile("[\\uE000-\\uF8FF\\u{F0000}-\\u{FFFFD}\\u{100000}-\\u{10FFFD}]").freeze SCHEME = Regexp.compile("[A-Za-z](?:[A-Za-z0-9+-\.])*").freeze PORT = Regexp.compile("[0-9]*").freeze IP_literal = Regexp.compile("\\[[0-9A-Fa-f:\\.]*\\]").freeze # Simplified, no IPvFuture PCT_ENCODED = Regexp.compile("%[0-9A-Fa-f][0-9A-Fa-f]").freeze - GEN_DELIMS = Regexp.compile("[:/\\?\\#\\[\\]@]").freeze - SUB_DELIMS = Regexp.compile("[!\\$&'\\(\\)\\*\\+,;=]").freeze - RESERVED = Regexp.compile("(?:#{GEN_DELIMS}|#{SUB_DELIMS})").freeze + GEN_DELIMS = Regexp.compile(%q{[:/\?\#\[\]@]}).freeze + SUB_DELIMS = Regexp.compile(%q{[!\$&'\(\)\*\+,;=]}).freeze + RESERVED = Regexp.union(GEN_DELIMS, SUB_DELIMS).freeze UNRESERVED = Regexp.compile("[A-Za-z0-9\._~-]").freeze - IUNRESERVED = Regexp.compile("[A-Za-z0-9\._~-]|#{UCSCHAR}").freeze + IUNRESERVED = Regexp.union(UNRESERVED, Regexp.compile("[#{UCSCHAR}]")).freeze - IPCHAR = Regexp.compile("(?:#{IUNRESERVED}|#{PCT_ENCODED}|#{SUB_DELIMS}|:|@)").freeze + IPCHAR = Regexp.union(IUNRESERVED, PCT_ENCODED, SUB_DELIMS, /[:|@]/).freeze IQUERY = Regexp.compile("(?:#{IPCHAR}|#{IPRIVATE}|/|\\?)*").freeze @@ -65,7 +66,7 @@ class URI IPATH_EMPTY = Regexp.compile("").freeze IREG_NAME = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS}))*").freeze - IHOST = Regexp.compile("(?:#{IP_literal})|(?:#{IREG_NAME})").freeze + IHOST = Regexp.union(IP_literal, IREG_NAME).freeze IUSERINFO = Regexp.compile("(?:(?:#{IUNRESERVED})|(?:#{PCT_ENCODED})|(?:#{SUB_DELIMS})|:)*").freeze IAUTHORITY = Regexp.compile("(?:#{IUSERINFO}@)?#{IHOST}(?::#{PORT})?").freeze @@ -116,7 +117,21 @@ class URI # Note: not all reserved characters need to be escaped in SPARQL/Turtle, but they must be unescaped when encountered PN_ESCAPE_CHARS = /[~\.!\$&'\(\)\*\+,;=\/\?\#@%]/.freeze PN_ESCAPES = /\\#{Regexp.union(PN_ESCAPE_CHARS, /[\-_]/)}/.freeze - + + # For URI encoding + # iuserinfo = *( iunreserved / pct-encoded / sub-delims / ":" ) + ENCODE_USER = + ENCODE_PASSWORD = Regexp.compile("[^A-Za-z0-9\._~#{UCSCHAR}!$&'\(\)\*\+,;=:-]").freeze + # isegment = *ipchar + # ipchar = iunreserved / pct-encoded / sub-delims / ":" / "@" + ENCODE_ISEGMENT = Regexp.compile("[^A-Za-z0-9\._~#{UCSCHAR}!$&'\(\)\*\+,;=:-]").freeze + # isegment-nz-nc = 1*( iunreserved / pct-encoded / sub-delims / "@" ) + ENCODE_ISEGMENT_NC = Regexp.compile("[^A-Za-z0-9\._~#{UCSCHAR}!$&'\(\)\*\+,;=-]").freeze + # iquery = *( ipchar / iprivate / "/" / "?" ) + ENCODE_IQUERY = Regexp.compile("[^A-Za-z0-9\._~#{UCSCHAR}\\uE000-\\uF8FF\\u{F0000}-\\u{FFFFD}\\u{100000}-\\u{10FFFD}/?=]").freeze + # ifragment = *( ipchar / "/" / "?" ) + ENCODE_IFRAGMENT = Regexp.compile("[^A-Za-z0-9\._~#{UCSCHAR}/?]").freeze + ## # Cache size may be set through {RDF.config} using `uri_cache_size`. # @@ -170,7 +185,7 @@ def self.parse(str) # @return [String] normalized path # @see http://tools.ietf.org/html/rfc3986#section-5.2.4 def self.normalize_path(path) - output, input = "", path.to_s + output, input = String.new, path.to_s if input.encoding != Encoding::ASCII_8BIT input = input.dup.force_encoding(Encoding::ASCII_8BIT) end @@ -353,7 +368,7 @@ def length # @return [Boolean] `true` or `false` # @since 0.3.9 def valid? - RDF::URI::IRI.match(to_s) || false + RDF::URI::IRI.match?(to_s) || false end ## @@ -920,7 +935,7 @@ def scheme=(value) # Return normalized version of scheme, if any # @return [String] def normalized_scheme - normalize_segment(scheme.strip, SCHEME, true) if scheme + scheme.strip.downcase if scheme end ## @@ -946,7 +961,7 @@ def user=(value) # Normalized version of user # @return [String] def normalized_user - URI.encode(CGI.unescape(user), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if user + URI.encode(CGI.unescape(user), ENCODE_USER).force_encoding(Encoding::UTF_8) if user end ## @@ -972,7 +987,7 @@ def password=(value) # Normalized version of password # @return [String] def normalized_password - URI.encode(CGI.unescape(password), /[^#{IUNRESERVED}|#{SUB_DELIMS}]/).force_encoding(Encoding::UTF_8) if password + URI.encode(CGI.unescape(password), ENCODE_PASSWORD).force_encoding(Encoding::UTF_8) if password end HOST_FROM_AUTHORITY_RE = /(?:[^@]+@)?([^:]+)(?::.*)?$/.freeze @@ -1000,7 +1015,7 @@ def host=(value) # @return [String] def normalized_host # Remove trailing '.' characters - normalize_segment(host, IHOST, true).chomp('.') if host + host.sub(/\.*$/, '').downcase if host end PORT_FROM_AUTHORITY_RE = /:(\d+)$/.freeze @@ -1028,12 +1043,8 @@ def port=(value) # @return [String] def normalized_port if port - np = normalize_segment(port.to_s, PORT) - if PORT_MAPPING[normalized_scheme] == np.to_i - nil - else - np.to_i - end + np = port.to_i + PORT_MAPPING[normalized_scheme] != np ? np : nil end end @@ -1064,30 +1075,36 @@ def path=(value) # Normalized version of path # @return [String] def normalized_path + if normalized_scheme == "urn" + # Special-case URI. Normalize the NID component only + nid, p = path.to_s.split(':', 2) + return "#{nid.downcase}:#{p}" + end + segments = path.to_s.split('/', -1) # preserve null segments norm_segs = case when authority # ipath-abempty - segments.map {|s| normalize_segment(s, ISEGMENT)} + segments.map {|s| normalize_segment(s, ENCODE_ISEGMENT)} when segments[0].nil? # ipath-absolute res = [nil] - res << normalize_segment(segments[1], ISEGMENT_NZ) if segments.length > 1 - res += segments[2..-1].map {|s| normalize_segment(s, ISEGMENT)} if segments.length > 2 + res << normalize_segment(segments[1], ENCODE_ISEGMENT) if segments.length > 1 + res += segments[2..-1].map {|s| normalize_segment(s, ENCODE_ISEGMENT)} if segments.length > 2 res when segments[0].to_s.index(':') # ipath-noscheme res = [] - res << normalize_segment(segments[0], ISEGMENT_NZ_NC) - res += segments[1..-1].map {|s| normalize_segment(s, ISEGMENT)} if segments.length > 1 + res << normalize_segment(segments[0], ENCODE_ISEGMENT_NC) + res += segments[1..-1].map {|s| normalize_segment(s, ENCODE_ISEGMENT)} if segments.length > 1 res when segments[0] # ipath-rootless # ipath-noscheme res = [] - res << normalize_segment(segments[0], ISEGMENT_NZ) - res += segments[1..-1].map {|s| normalize_segment(s, ISEGMENT)} if segments.length > 1 + res << normalize_segment(segments[0], ENCODE_ISEGMENT) + res += segments[1..-1].map {|s| normalize_segment(s, ENCODE_ISEGMENT)} if segments.length > 1 res else # Should be empty @@ -1096,7 +1113,7 @@ def normalized_path res = self.class.normalize_path(norm_segs.join("/")) # Special rules for specific protocols having empty paths - normalize_segment(res.empty? ? (%w(http https ftp tftp).include?(normalized_scheme) ? '/' : "") : res, IHIER_PART) + (res.empty? && %w(http https ftp tftp).include?(normalized_scheme)) ? '/' : res end ## @@ -1120,7 +1137,7 @@ def query=(value) # Normalized version of query # @return [String] def normalized_query - normalize_segment(query, IQUERY) if query + normalize_segment(query, ENCODE_IQUERY) if query end ## @@ -1144,7 +1161,7 @@ def fragment=(value) # Normalized version of fragment # @return [String] def normalized_fragment - normalize_segment(fragment, IFRAGMENT) if fragment + normalize_segment(fragment, ENCODE_IFRAGMENT) if fragment end ## @@ -1274,7 +1291,7 @@ def query_values=(value) self.query = case value when Array, Hash value.map do |(k,v)| - k = normalize_segment(k.to_s, UNRESERVED) + k = normalize_segment(k.to_s, /[^A-Za-z0-9\._~-]/) if v.nil? k else @@ -1282,7 +1299,7 @@ def query_values=(value) if vv === TrueClass k else - "#{k}=#{normalize_segment(vv.to_s, UNRESERVED)}" + "#{k}=#{normalize_segment(vv.to_s, /[^A-Za-z0-9\._~-]/)}" end end.join("&") end @@ -1331,7 +1348,7 @@ def self._load(data) # Normalize a segment using a character range # # @param [String] value - # @param [Regexp] expr + # @param [Regexp] expr matches characters to be encoded # @param [Boolean] downcase # @return [String] def normalize_segment(value, expr, downcase = false) @@ -1339,7 +1356,7 @@ def normalize_segment(value, expr, downcase = false) value = value.dup.force_encoding(Encoding::UTF_8) decoded = CGI.unescape(value) decoded.downcase! if downcase - URI.encode(decoded, /[^(?:#{expr})]/).force_encoding(Encoding::UTF_8) + URI.encode(decoded, expr).force_encoding(Encoding::UTF_8) end end @@ -1364,7 +1381,7 @@ def format_authority def self.encode(str, expr) str.gsub(expr) do us = $& - tmp = '' + tmp = String.new us.each_byte do |uc| tmp << sprintf('%%%02X', uc) end diff --git a/lib/rdf/util/cache.rb b/lib/rdf/util/cache.rb index 56fd5598..7426f8aa 100644 --- a/lib/rdf/util/cache.rb +++ b/lib/rdf/util/cache.rb @@ -127,7 +127,7 @@ def initialize(capacity = nil) def [](key) if (ref = @cache[key]) if ref.weakref_alive? - value = ref.__getobj__ rescue nil + ref.__getobj__ rescue nil else @cache.delete(key) nil diff --git a/lib/rdf/util/uuid.rb b/lib/rdf/util/uuid.rb index 4ae38dc2..e85df193 100644 --- a/lib/rdf/util/uuid.rb +++ b/lib/rdf/util/uuid.rb @@ -22,11 +22,11 @@ def self.generate(format: :default) begin require 'uuid' ::UUID.generate(format) - rescue LoadError => e + rescue LoadError begin require 'uuidtools' ::UUIDTools::UUID.random_create.hexdigest - rescue LoadError => e + rescue LoadError raise LoadError.new("no such file to load -- uuid or uuidtools") end end diff --git a/spec/mixin_queryable_spec.rb b/spec/mixin_queryable_spec.rb index 15ed71c0..9b8f66a5 100644 --- a/spec/mixin_queryable_spec.rb +++ b/spec/mixin_queryable_spec.rb @@ -29,7 +29,7 @@ end context "Querying for solutions from a BGP" do - let(:query) { query = RDF::Query.new {pattern %i(s p o)} } + let(:query) { RDF::Query.new {pattern %i(s p o)} } it "calls #query_execute" do is_expected.to receive(:query_execute) is_expected.not_to receive(:query_pattern) diff --git a/spec/model_list_spec.rb b/spec/model_list_spec.rb index 775a277d..b89bee44 100644 --- a/spec/model_list_spec.rb +++ b/spec/model_list_spec.rb @@ -163,14 +163,13 @@ context :with_transaction do it "uses a transaction for the graph" do n = RDF::Node.new - l = RDF::List.new(subject: n, graph: graph, wrap_transaction: true) do |list| + RDF::List.new(subject: n, graph: graph, wrap_transaction: true) do |list| expect(list.graph).to be_a(RDF::Transaction) expect(list.graph).not_to equal graph end end it "adds values in a transaction" do - n = RDF::Node.new l = RDF::List.new(graph: graph, wrap_transaction: true) do |list| list << RDF::Literal(1) expect(graph.first_object(subject: list.subject, predicate: RDF.first)).to be_nil @@ -180,7 +179,6 @@ end it "rollback added values in a transaction" do - n = RDF::Node.new l = RDF::List.new(graph: graph, wrap_transaction: true) do |list| list << RDF::Literal(1) expect(graph.first_object(subject: list.subject, predicate: RDF.first)).to be_nil diff --git a/spec/model_uri_spec.rb b/spec/model_uri_spec.rb index 76fd1eed..8d00d7ba 100644 --- a/spec/model_uri_spec.rb +++ b/spec/model_uri_spec.rb @@ -317,75 +317,94 @@ %W(\U00000053 Dürst AZazÀÖØöø˿Ͱͽ΄῾‌‍⁰↉Ⰰ⿕、ퟻ﨎ﷇﷰ￯𐀀𪘀) } { - "" => "%s", - "and query" => "%s?%s", - "and fragment" => "%s#%s", - "and query and fragment" => "%s?%s#%s", + "" => "%{p1}", + "and query" => "%{p1}?%{p2}", + "and fragment" => "%{p1}#%{p2}", + "and query and fragment" => "%{p1}?%{p2}#%{p3}", }.each do |mod, fmt| it "validates IRI with authority and ipath-abempty #{mod}" do refs.each do |c| - expect(RDF::URI("scheme://auth/#{fmt}" % ["", c, c])).to be_valid - expect(RDF::URI("scheme://auth/#{fmt}" % [c, c, c])).to be_valid - expect(RDF::URI("scheme://auth/#{fmt}" % ["#{c}/#{c}", c, c])).to be_valid + expect(RDF::URI("scheme://auth/#{fmt}" % {p1: "", p2: c, p3: c})).to be_valid + expect(RDF::URI("scheme://auth/#{fmt}" % {p1: c, p2: c, p3: c})).to be_valid + expect(RDF::URI("scheme://auth/#{fmt}" % {p1: "#{c}/#{c}", p2: c, p3: c})).to be_valid end end it "validates IRI with path-absolute #{mod}" do refs.each do |c| - expect(RDF::URI("scheme:/#{fmt}" % ["", c, c])).to be_valid - expect(RDF::URI("scheme:/#{fmt}" % [c, c, c])).to be_valid - expect(RDF::URI("scheme:/#{fmt}" % ["#{c}/#{c}", c, c])).to be_valid + expect(RDF::URI("scheme:/#{fmt}" % {p1: "", p2: c, p3: c})).to be_valid + expect(RDF::URI("scheme:/#{fmt}" % {p1: c, p2: c, p3: c})).to be_valid + expect(RDF::URI("scheme:/#{fmt}" % {p1: "#{c}/#{c}", p2: c, p3: c})).to be_valid end end it "validates IRI with ipath-rootless #{mod}" do refs.each do |c| - expect(RDF::URI("scheme:#{fmt}" % [c, c, c])).to be_valid - expect(RDF::URI("scheme:#{fmt}" % ["#{c}/#{c}", c, c])).to be_valid + expect(RDF::URI("scheme:#{fmt}" % {p1: c, p2: c, p3: c})).to be_valid + expect(RDF::URI("scheme:#{fmt}" % {p1: "#{c}/#{c}", p2: c, p3: c})).to be_valid end end it "validates IRI with ipath-empty #{mod}" do refs.each do |c| - expect(RDF::URI("scheme:#{fmt}" % ["", c, c])).to be_valid + expect(RDF::URI("scheme:#{fmt}" % {p1: "", p2: c, p3: c})).to be_valid end end it "invalidates irelative-ref with authority #{mod}" do refs.each do |c| - expect(RDF::URI("//auth/#{fmt}" % [c, c, c])).not_to be_valid + expect(RDF::URI("//auth/#{fmt}" % {p1: c, p2: c, p3: c})).not_to be_valid end end it "invalidates irelative-ref with authority and port #{mod}" do refs.each do |c| - expect(RDF::URI("//auth:123/#{fmt}" % [c, c, c])).not_to be_valid + expect(RDF::URI("//auth:123/#{fmt}" % {p1: c, p2: c, p3: c})).not_to be_valid end end it "invalidates irelative-ref with ipath-absolute #{mod}" do refs.each do |c| - expect(RDF::URI("/#{fmt}" % [c, c, c])).not_to be_valid - expect(RDF::URI("/#{fmt}" % ["#{c}/", c, c])).not_to be_valid - expect(RDF::URI("/#{fmt}" % ["#{c}/#{c}", c, c])).not_to be_valid + expect(RDF::URI("/#{fmt}" % {p1: c, p2: c, p3: c})).not_to be_valid + expect(RDF::URI("/#{fmt}" % {p1: "#{c}/", p2: c, p3: c})).not_to be_valid + expect(RDF::URI("/#{fmt}" % {p1: "#{c}/#{c}", p2: c, p3: c})).not_to be_valid end end it "invalidates irelative-ref with ipath-noscheme #{mod}" do refs.each do |c| - expect(RDF::URI("#{fmt}" % [c, c, c])).not_to be_valid - expect(RDF::URI("#{fmt}" % ["#{c}/", c, c])).not_to be_valid - expect(RDF::URI("#{fmt}" % ["#{c}/#{c}", c, c])).not_to be_valid + expect(RDF::URI("#{fmt}" % {p1: c, p2: c, p3: c})).not_to be_valid + expect(RDF::URI("#{fmt}" % {p1: "#{c}/", p2: c, p3: c})).not_to be_valid + expect(RDF::URI("#{fmt}" % {p1: "#{c}/#{c}", p2: c, p3: c})).not_to be_valid end end it "invalidates irelative-ref with ipath-empty #{mod}" do refs.each do |c| - expect(RDF::URI("#{fmt}" % ["", c, c])).not_to be_valid + expect(RDF::URI("#{fmt}" % {p1: "", p2: c, p3: c})).not_to be_valid end end end - %W(` ^ \\ \u0000 \u0001 \u0002 \u0003 \u0004 \u0005 \u0006 + (%W(` ^ \\ \u0000 \u0001 \u0002 \u0003 \u0004 \u0005 \u0006 \u0010 \u0020 \u003c \u003e \u0022 \u007b \u007d) + - [" ", "<", ">", "'" '"'].each do |c| + [" ", "<", ">", "'" '"']).each do |c| it "does not validate " do expect(RDF::URI("http://example/#{c}")).not_to be_valid end end + + [ + 'file:///path/to/file with spaces.txt', + 'scheme://auth/\u0000', + 'scheme://auth/\u005C', + 'scheme://auth/\u005E', + 'scheme://auth/\u0060', + 'scheme://auth/\\u0000', + 'scheme://auth/\\u005C', + 'scheme://auth/\\u005E', + 'scheme://auth/\\u0060', + 'scheme://auth/^', + 'scheme://auth/`', + 'scheme://auth/\\', + ].each do |u| + it "does not validate <#{u}>" do + expect(RDF::URI(u)).not_to be_valid + end + end end describe "#invalid?" do @@ -500,9 +519,9 @@ it "#canonicalize #{name}" do u1 = RDF::URI(input) u2 = RDF::URI(output) - expect(u1.canonicalize.hash).to eq u2.hash expect(u1.canonicalize.to_s).to eq u2.to_s expect(u1.canonicalize).to eq u1.canonicalize + expect(u1.canonicalize.hash).to eq u2.hash end end it "#canonicalize! alters resource" do diff --git a/spec/nquads_spec.rb b/spec/nquads_spec.rb index 95f0004e..e88b579c 100644 --- a/spec/nquads_spec.rb +++ b/spec/nquads_spec.rb @@ -14,7 +14,7 @@ subject { described_class } describe ".for" do - formats = [ + [ :nquads, 'etc/doap.nq', {file_name: 'etc/doap.nq'}, @@ -99,7 +99,7 @@ end describe ".for" do - formats = [ + [ :nquads, 'etc/doap.nq', {file_name: 'etc/doap.nq'}, @@ -236,7 +236,7 @@ subject { RDF::NQuads::Writer.new } describe ".for" do - formats = [ + [ :nquads, 'etc/doap.nq', {file_name: 'etc/doap.nq'}, diff --git a/spec/query_spec.rb b/spec/query_spec.rb index bdb31fb3..1aa98941 100644 --- a/spec/query_spec.rb +++ b/spec/query_spec.rb @@ -968,7 +968,7 @@ context "Examples" do let!(:graph) {RDF::Graph.new.insert(RDF::Spec.triples.extend(RDF::Enumerable))} subject { - query = RDF::Query.new do + RDF::Query.new do pattern [:person, RDF.type, FOAF.Person] pattern [:person, FOAF.name, :name] pattern [:person, FOAF.mbox, :email] diff --git a/spec/reader_spec.rb b/spec/reader_spec.rb index 25ae7046..a3555ac4 100644 --- a/spec/reader_spec.rb +++ b/spec/reader_spec.rb @@ -59,7 +59,6 @@ it "uses content type in preference to file extension" do uri = "http://example/foo.nq" - accept = (RDF::Format.accept_types + %w(*/*;q=0.1)).join(", ") reader_mock = double("reader") expect(reader_mock).to receive(:got_here) WebMock. @@ -74,7 +73,6 @@ it "ignores content type 'text/plain'" do uri = "http://example/foo.ttl" - accept = (RDF::Format.accept_types + %w(*/*;q=0.1)).join(", ") reader_mock = double("reader") expect(reader_mock).to receive(:got_here) WebMock. diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7db312a4..b98a8db3 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -42,3 +42,5 @@ def fixture_path(filename) Encoding.default_external = Encoding::UTF_8 Encoding.default_internal = Encoding::UTF_8 + +$VERBOSE = true diff --git a/spec/util_logger_spec.rb b/spec/util_logger_spec.rb index 50e4ee28..11cee1ce 100644 --- a/spec/util_logger_spec.rb +++ b/spec/util_logger_spec.rb @@ -48,7 +48,7 @@ def initialize(logger = nil) it "adds locaton to log message" do expect {subject.log_fatal("foo")}.to raise_error(StandardError) - expect(subject.logger.to_s).to match /Called from #{File.expand_path("", __FILE__)}:#{__LINE__-1}/ + expect(subject.logger.to_s).to match(/Called from #{File.expand_path("", __FILE__)}:#{__LINE__-1}/) end it "logs to $stderr if logger not configured" do