public_suffix 2.0.5 → 4.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +5 -5
  2. data/.github/FUNDING.yml +12 -0
  3. data/.github/dependabot.yml +8 -0
  4. data/.github/workflows/release.yml +16 -0
  5. data/.github/workflows/tests.yml +28 -0
  6. data/.gitignore +5 -8
  7. data/.rubocop.yml +19 -1
  8. data/{.rubocop_defaults.yml → .rubocop_opinionated.yml} +62 -34
  9. data/CHANGELOG.md +156 -54
  10. data/Gemfile +9 -5
  11. data/LICENSE.txt +1 -1
  12. data/README.md +44 -15
  13. data/Rakefile +9 -4
  14. data/SECURITY.md +104 -0
  15. data/bin/console +15 -0
  16. data/data/list.txt +3163 -973
  17. data/lib/public_suffix/domain.rb +4 -4
  18. data/lib/public_suffix/errors.rb +3 -1
  19. data/lib/public_suffix/list.rb +78 -117
  20. data/lib/public_suffix/rule.rb +54 -62
  21. data/lib/public_suffix/version.rb +8 -3
  22. data/lib/public_suffix.rb +38 -32
  23. data/public_suffix.gemspec +9 -5
  24. data/test/.empty +2 -0
  25. data/test/acceptance_test.rb +43 -31
  26. data/test/benchmarks/bm_find.rb +66 -0
  27. data/test/benchmarks/bm_find_all.rb +102 -0
  28. data/test/benchmarks/bm_names.rb +91 -0
  29. data/test/benchmarks/bm_select.rb +26 -0
  30. data/test/benchmarks/bm_select_incremental.rb +25 -0
  31. data/test/benchmarks/bm_valid.rb +101 -0
  32. data/test/profilers/domain_profiler.rb +12 -0
  33. data/test/profilers/find_profiler.rb +12 -0
  34. data/test/profilers/find_profiler_jp.rb +12 -0
  35. data/test/{initialization_profiler.rb → profilers/initialization_profiler.rb} +1 -1
  36. data/test/profilers/list_profsize.rb +11 -0
  37. data/test/profilers/object_binsize.rb +57 -0
  38. data/test/psl_test.rb +7 -4
  39. data/test/test_helper.rb +3 -14
  40. data/test/unit/domain_test.rb +17 -15
  41. data/test/unit/errors_test.rb +2 -0
  42. data/test/unit/list_test.rb +54 -72
  43. data/test/unit/public_suffix_test.rb +24 -22
  44. data/test/unit/rule_test.rb +77 -79
  45. metadata +32 -70
  46. data/.ruby-gemset +0 -1
  47. data/.travis.yml +0 -23
  48. data/test/benchmark_helper.rb +0 -4
  49. data/test/execution_profiler.rb +0 -14
  50. data/test/performance_benchmark.rb +0 -38
data/lib/public_suffix.rb CHANGED
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # = Public Suffix
2
4
  #
3
5
  # Domain name parser based on the Public Suffix List.
4
6
  #
5
- # Copyright (c) 2009-2017 Simone Carletti <weppos@weppos.net>
7
+ # Copyright (c) 2009-2022 Simone Carletti <weppos@weppos.net>
6
8
 
7
- require "public_suffix/domain"
8
- require "public_suffix/version"
9
- require "public_suffix/errors"
10
- require "public_suffix/rule"
11
- require "public_suffix/list"
9
+ require_relative "public_suffix/domain"
10
+ require_relative "public_suffix/version"
11
+ require_relative "public_suffix/errors"
12
+ require_relative "public_suffix/rule"
13
+ require_relative "public_suffix/list"
12
14
 
13
15
  # PublicSuffix is a Ruby domain name parser based on the Public Suffix List.
14
16
  #
@@ -20,46 +22,48 @@ require "public_suffix/list"
20
22
  # but was originally created to meet the needs of browser manufacturers.
21
23
  module PublicSuffix
22
24
 
23
- DOT = ".".freeze
24
- BANG = "!".freeze
25
- STAR = "*".freeze
25
+ DOT = "."
26
+ BANG = "!"
27
+ STAR = "*"
26
28
 
27
29
  # Parses +name+ and returns the {PublicSuffix::Domain} instance.
28
30
  #
29
31
  # @example Parse a valid domain
30
32
  # PublicSuffix.parse("google.com")
31
- # # => #<PublicSuffix::Domain ...>
33
+ # # => #<PublicSuffix::Domain:0x007fec2e51e588 @sld="google", @tld="com", @trd=nil>
32
34
  #
33
35
  # @example Parse a valid subdomain
34
36
  # PublicSuffix.parse("www.google.com")
35
- # # => #<PublicSuffix::Domain ...>
37
+ # # => #<PublicSuffix::Domain:0x007fec276d4cf8 @sld="google", @tld="com", @trd="www">
36
38
  #
37
39
  # @example Parse a fully qualified domain
38
40
  # PublicSuffix.parse("google.com.")
39
- # # => #<PublicSuffix::Domain ...>
41
+ # # => #<PublicSuffix::Domain:0x007fec257caf38 @sld="google", @tld="com", @trd=nil>
40
42
  #
41
43
  # @example Parse a fully qualified domain (subdomain)
42
44
  # PublicSuffix.parse("www.google.com.")
43
- # # => #<PublicSuffix::Domain ...>
45
+ # # => #<PublicSuffix::Domain:0x007fec27b6bca8 @sld="google", @tld="com", @trd="www">
44
46
  #
45
- # @example Parse an invalid domain
47
+ # @example Parse an invalid (unlisted) domain
46
48
  # PublicSuffix.parse("x.yz")
47
- # # => PublicSuffix::DomainInvalid
49
+ # # => #<PublicSuffix::Domain:0x007fec2f49bec0 @sld="x", @tld="yz", @trd=nil>
50
+ #
51
+ # @example Parse an invalid (unlisted) domain with strict checking (without applying the default * rule)
52
+ # PublicSuffix.parse("x.yz", default_rule: nil)
53
+ # # => PublicSuffix::DomainInvalid: `x.yz` is not a valid domain
48
54
  #
49
55
  # @example Parse an URL (not supported, only domains)
50
56
  # PublicSuffix.parse("http://www.google.com")
51
- # # => PublicSuffix::DomainInvalid
57
+ # # => PublicSuffix::DomainInvalid: http://www.google.com is not expected to contain a scheme
52
58
  #
53
59
  #
54
- # @param [String, #to_s] name The domain name or fully qualified domain name to parse.
55
- # @param [PublicSuffix::List] list The rule list to search, defaults to the default {PublicSuffix::List}
56
- # @param [Boolean] ignore_private
60
+ # @param name [#to_s] The domain name or fully qualified domain name to parse.
61
+ # @param list [PublicSuffix::List] The rule list to search, defaults to the default {PublicSuffix::List}
62
+ # @param ignore_private [Boolean]
57
63
  # @return [PublicSuffix::Domain]
58
64
  #
59
- # @raise [PublicSuffix::DomainInvalid]
60
- # If domain is not a valid domain.
61
- # @raise [PublicSuffix::DomainNotAllowed]
62
- # If a rule for +domain+ is found, but the rule doesn't allow +domain+.
65
+ # @raise [PublicSuffix::DomainInvalid] If domain is not a valid domain.
66
+ # @raise [PublicSuffix::DomainNotAllowed] If a rule for +domain+ is found, but the rule doesn't allow +domain+.
63
67
  def self.parse(name, list: List.default, default_rule: list.default_rule, ignore_private: false)
64
68
  what = normalize(name)
65
69
  raise what if what.is_a?(DomainInvalid)
@@ -73,6 +77,7 @@ module PublicSuffix
73
77
  if rule.decompose(what).last.nil?
74
78
  raise DomainNotAllowed, "`#{what}` is not allowed according to Registry policy"
75
79
  end
80
+
76
81
  # rubocop:enable Style/IfUnlessModifier
77
82
 
78
83
  decompose(what, rule)
@@ -95,11 +100,11 @@ module PublicSuffix
95
100
  # PublicSuffix.valid?("example.tldnotlisted")
96
101
  # # => true
97
102
  #
98
- # @example Validate a not-allowed domain
99
- # PublicSuffix.valid?("example.do")
100
- # # => false
101
- # PublicSuffix.valid?("www.example.do")
103
+ # @example Validate a not-listed domain with strict checking (without applying the default * rule)
104
+ # PublicSuffix.valid?("example.tldnotlisted")
102
105
  # # => true
106
+ # PublicSuffix.valid?("example.tldnotlisted", default_rule: nil)
107
+ # # => false
103
108
  #
104
109
  # @example Validate a fully qualified domain
105
110
  # PublicSuffix.valid?("google.com.")
@@ -112,8 +117,8 @@ module PublicSuffix
112
117
  # # => false
113
118
  #
114
119
  #
115
- # @param [String, #to_s] name The domain name or fully qualified domain name to validate.
116
- # @param [Boolean] ignore_private
120
+ # @param name [#to_s] The domain name or fully qualified domain name to validate.
121
+ # @param ignore_private [Boolean]
117
122
  # @return [Boolean]
118
123
  def self.valid?(name, list: List.default, default_rule: list.default_rule, ignore_private: false)
119
124
  what = normalize(name)
@@ -128,9 +133,9 @@ module PublicSuffix
128
133
  #
129
134
  # This method doesn't raise. Instead, it returns nil if the domain is not valid for whatever reason.
130
135
  #
131
- # @param [String, #to_s] name The domain name or fully qualified domain name to parse.
132
- # @param [PublicSuffix::List] list The rule list to search, defaults to the default {PublicSuffix::List}
133
- # @param [Boolean] ignore_private
136
+ # @param name [#to_s] The domain name or fully qualified domain name to parse.
137
+ # @param list [PublicSuffix::List] The rule list to search, defaults to the default {PublicSuffix::List}
138
+ # @param ignore_private [Boolean]
134
139
  # @return [String]
135
140
  def self.domain(name, **options)
136
141
  parse(name, **options).domain
@@ -165,6 +170,7 @@ module PublicSuffix
165
170
  return DomainInvalid.new("Name is blank") if name.empty?
166
171
  return DomainInvalid.new("Name starts with a dot") if name.start_with?(DOT)
167
172
  return DomainInvalid.new("%s is not expected to contain a scheme" % name) if name.include?("://")
173
+
168
174
  name
169
175
  end
170
176
 
@@ -12,14 +12,18 @@ Gem::Specification.new do |s|
12
12
  s.description = "PublicSuffix can parse and decompose a domain name into top level domain, domain and subdomains."
13
13
  s.licenses = ["MIT"]
14
14
 
15
- s.required_ruby_version = ">= 2.0"
15
+ s.metadata = {
16
+ "bug_tracker_uri" => "https://github.com/weppos/publicsuffix-ruby/issues",
17
+ "changelog_uri" => "https://github.com/weppos/publicsuffix-ruby/blob/master/CHANGELOG.md",
18
+ "documentation_uri" => "https://rubydoc.info/gems/#{s.name}/#{s.version}",
19
+ "homepage_uri" => s.homepage,
20
+ "source_code_uri" => "https://github.com/weppos/publicsuffix-ruby/tree/v#{s.version}",
21
+ }
22
+
23
+ s.required_ruby_version = ">= 2.3"
16
24
 
17
25
  s.require_paths = ["lib"]
18
26
  s.files = `git ls-files`.split("\n")
19
27
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
28
  s.extra_rdoc_files = %w( LICENSE.txt )
21
-
22
- s.add_development_dependency "rake"
23
- s.add_development_dependency "mocha"
24
- s.add_development_dependency "yard"
25
29
  end
data/test/.empty ADDED
@@ -0,0 +1,2 @@
1
+ # This is an empty file I use to force a non-empty commit when I only need to store notes
2
+ ..
@@ -1,16 +1,18 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "test_helper"
2
4
 
3
5
  class AcceptanceTest < Minitest::Test
4
6
 
5
7
  VALID_CASES = [
6
- ["example.com", "example.com", [nil, "example", "com"]],
7
- ["foo.example.com", "example.com", ["foo", "example", "com"]],
8
+ ["example.com", "example.com", [nil, "example", "com"]],
9
+ ["foo.example.com", "example.com", ["foo", "example", "com"]],
8
10
 
9
- ["verybritish.co.uk", "verybritish.co.uk", [nil, "verybritish", "co.uk"]],
10
- ["foo.verybritish.co.uk", "verybritish.co.uk", ["foo", "verybritish", "co.uk"]],
11
+ ["verybritish.co.uk", "verybritish.co.uk", [nil, "verybritish", "co.uk"]],
12
+ ["foo.verybritish.co.uk", "verybritish.co.uk", ["foo", "verybritish", "co.uk"]],
11
13
 
12
- ["parliament.uk", "parliament.uk", [nil, "parliament", "uk"]],
13
- ["foo.parliament.uk", "parliament.uk", ["foo", "parliament", "uk"]],
14
+ ["parliament.uk", "parliament.uk", [nil, "parliament", "uk"]],
15
+ ["foo.parliament.uk", "parliament.uk", ["foo", "parliament", "uk"]],
14
16
  ].freeze
15
17
 
16
18
  def test_valid
@@ -19,7 +21,11 @@ class AcceptanceTest < Minitest::Test
19
21
  trd, sld, tld = results
20
22
  assert_equal tld, parsed.tld, "Invalid tld for `#{name}`"
21
23
  assert_equal sld, parsed.sld, "Invalid sld for `#{name}`"
22
- assert_equal trd, parsed.trd, "Invalid trd for `#{name}`"
24
+ if trd.nil?
25
+ assert_nil parsed.trd, "Invalid trd for `#{name}`"
26
+ else
27
+ assert_equal trd, parsed.trd, "Invalid trd for `#{name}`"
28
+ end
23
29
 
24
30
  assert_equal domain, PublicSuffix.domain(input)
25
31
  assert PublicSuffix.valid?(input)
@@ -28,10 +34,10 @@ class AcceptanceTest < Minitest::Test
28
34
 
29
35
 
30
36
  INVALID_CASES = [
31
- ["nic.ke", PublicSuffix::DomainNotAllowed],
32
- [nil, PublicSuffix::DomainInvalid],
33
- ["", PublicSuffix::DomainInvalid],
34
- [" ", PublicSuffix::DomainInvalid],
37
+ ["nic.bd", PublicSuffix::DomainNotAllowed],
38
+ [nil, PublicSuffix::DomainInvalid],
39
+ ["", PublicSuffix::DomainInvalid],
40
+ [" ", PublicSuffix::DomainInvalid],
35
41
  ].freeze
36
42
 
37
43
  def test_invalid
@@ -43,16 +49,16 @@ class AcceptanceTest < Minitest::Test
43
49
 
44
50
 
45
51
  REJECTED_CASES = [
46
- ["www. .com", true],
47
- ["foo.co..uk", true],
48
- ["goo,gle.com", true],
49
- ["-google.com", true],
50
- ["google-.com", true],
51
-
52
- # This case was covered in GH-15.
53
- # I decided to cover this case because it's not easily reproducible with URI.parse
54
- # and can lead to several false positives.
55
- ["http://google.com", false],
52
+ ["www. .com", true],
53
+ ["foo.co..uk", true],
54
+ ["goo,gle.com", true],
55
+ ["-google.com", true],
56
+ ["google-.com", true],
57
+
58
+ # This case was covered in GH-15.
59
+ # I decided to cover this case because it's not easily reproducible with URI.parse
60
+ # and can lead to several false positives.
61
+ ["http://google.com", false],
56
62
  ].freeze
57
63
 
58
64
  def test_rejected
@@ -66,9 +72,9 @@ class AcceptanceTest < Minitest::Test
66
72
 
67
73
 
68
74
  CASE_CASES = [
69
- ["Www.google.com", %w( www google com )],
70
- ["www.Google.com", %w( www google com )],
71
- ["www.google.Com", %w( www google com )],
75
+ ["Www.google.com", %w( www google com )],
76
+ ["www.Google.com", %w( www google com )],
77
+ ["www.google.Com", %w( www google com )],
72
78
  ].freeze
73
79
 
74
80
  def test_ignore_case
@@ -84,35 +90,41 @@ class AcceptanceTest < Minitest::Test
84
90
 
85
91
 
86
92
  INCLUDE_PRIVATE_CASES = [
87
- ["blogspot.com", true, "blogspot.com"],
88
- ["blogspot.com", false, nil],
89
- ["subdomain.blogspot.com", true, "blogspot.com"],
90
- ["subdomain.blogspot.com", false, "subdomain.blogspot.com"],
93
+ ["blogspot.com", true, "blogspot.com"],
94
+ ["blogspot.com", false, nil],
95
+ ["subdomain.blogspot.com", true, "blogspot.com"],
96
+ ["subdomain.blogspot.com", false, "subdomain.blogspot.com"],
91
97
  ].freeze
92
98
 
99
+ # rubocop:disable Style/CombinableLoops
93
100
  def test_ignore_private
94
101
  # test domain and parse
95
102
  INCLUDE_PRIVATE_CASES.each do |given, ignore_private, expected|
96
- assert_equal expected, PublicSuffix.domain(given, ignore_private: ignore_private)
103
+ if expected.nil?
104
+ assert_nil PublicSuffix.domain(given, ignore_private: ignore_private)
105
+ else
106
+ assert_equal expected, PublicSuffix.domain(given, ignore_private: ignore_private)
107
+ end
97
108
  end
98
109
  # test valid?
99
110
  INCLUDE_PRIVATE_CASES.each do |given, ignore_private, expected|
100
111
  assert_equal !expected.nil?, PublicSuffix.valid?(given, ignore_private: ignore_private)
101
112
  end
102
113
  end
114
+ # rubocop:enable Style/CombinableLoops
103
115
 
104
116
 
105
117
  def valid_uri?(name)
106
118
  uri = URI.parse(name)
107
119
  !uri.host.nil?
108
- rescue
120
+ rescue StandardError
109
121
  false
110
122
  end
111
123
 
112
124
  def valid_domain?(name)
113
125
  uri = URI.parse(name)
114
126
  !uri.host.nil? && uri.scheme.nil?
115
- rescue
127
+ rescue StandardError
116
128
  false
117
129
  end
118
130
 
@@ -0,0 +1,66 @@
1
+ require 'benchmark'
2
+ require_relative "../../lib/public_suffix"
3
+
4
+ NAME_SHORT = "example.de"
5
+ NAME_MEDIUM = "www.subdomain.example.de"
6
+ NAME_LONG = "one.two.three.four.five.example.de"
7
+ NAME_WILD = "one.two.three.four.five.example.bd"
8
+ NAME_EXCP = "one.two.three.four.five.www.ck"
9
+
10
+ IAAA = "www.example.ac"
11
+ IZZZ = "www.example.zone"
12
+
13
+ PAAA = "one.two.three.four.five.example.beep.pl"
14
+ PZZZ = "one.two.three.four.five.example.now.sh"
15
+
16
+ JP = "www.yokoshibahikari.chiba.jp"
17
+ IT = "www.example.it"
18
+ COM = "www.example.com"
19
+
20
+ TIMES = (ARGV.first || 50_000).to_i
21
+
22
+ # Initialize
23
+ PublicSuffixList = PublicSuffix::List.default
24
+ PublicSuffixList.find("example.com")
25
+
26
+ Benchmark.bmbm(25) do |x|
27
+ x.report("NAME_SHORT") do
28
+ TIMES.times { PublicSuffixList.find(NAME_SHORT) != nil }
29
+ end
30
+ x.report("NAME_MEDIUM") do
31
+ TIMES.times { PublicSuffixList.find(NAME_MEDIUM) != nil }
32
+ end
33
+ x.report("NAME_LONG") do
34
+ TIMES.times { PublicSuffixList.find(NAME_LONG) != nil }
35
+ end
36
+ x.report("NAME_WILD") do
37
+ TIMES.times { PublicSuffixList.find(NAME_WILD) != nil }
38
+ end
39
+ x.report("NAME_EXCP") do
40
+ TIMES.times { PublicSuffixList.find(NAME_EXCP) != nil }
41
+ end
42
+
43
+ x.report("IAAA") do
44
+ TIMES.times { PublicSuffixList.find(IAAA) != nil }
45
+ end
46
+ x.report("IZZZ") do
47
+ TIMES.times { PublicSuffixList.find(IZZZ) != nil }
48
+ end
49
+
50
+ x.report("PAAA") do
51
+ TIMES.times { PublicSuffixList.find(PAAA) != nil }
52
+ end
53
+ x.report("PZZZ") do
54
+ TIMES.times { PublicSuffixList.find(PZZZ) != nil }
55
+ end
56
+
57
+ x.report("JP") do
58
+ TIMES.times { PublicSuffixList.find(JP) != nil }
59
+ end
60
+ x.report("IT") do
61
+ TIMES.times { PublicSuffixList.find(IT) != nil }
62
+ end
63
+ x.report("COM") do
64
+ TIMES.times { PublicSuffixList.find(COM) != nil }
65
+ end
66
+ end
@@ -0,0 +1,102 @@
1
+ require 'benchmark'
2
+ require_relative "../../lib/public_suffix"
3
+
4
+ NAME_SHORT = "example.de"
5
+ NAME_MEDIUM = "www.subdomain.example.de"
6
+ NAME_LONG = "one.two.three.four.five.example.de"
7
+ NAME_WILD = "one.two.three.four.five.example.bd"
8
+ NAME_EXCP = "one.two.three.four.five.www.ck"
9
+
10
+ IAAA = "www.example.ac"
11
+ IZZZ = "www.example.zone"
12
+
13
+ PAAA = "one.two.three.four.five.example.beep.pl"
14
+ PZZZ = "one.two.three.four.five.example.now.sh"
15
+
16
+ JP = "www.yokoshibahikari.chiba.jp"
17
+ IT = "www.example.it"
18
+ COM = "www.example.com"
19
+
20
+ TIMES = (ARGV.first || 50_000).to_i
21
+
22
+ # Initialize
23
+ PublicSuffixList = PublicSuffix::List.default
24
+ PublicSuffixList.find("example.com")
25
+
26
+ Benchmark.bmbm(25) do |x|
27
+ x.report("NAME_SHORT") do
28
+ TIMES.times { PublicSuffixList.find(NAME_SHORT) != nil }
29
+ end
30
+ x.report("NAME_SHORT (noprivate)") do
31
+ TIMES.times { PublicSuffixList.find(NAME_SHORT, ignore_private: true) != nil }
32
+ end
33
+ x.report("NAME_MEDIUM") do
34
+ TIMES.times { PublicSuffixList.find(NAME_MEDIUM) != nil }
35
+ end
36
+ x.report("NAME_MEDIUM (noprivate)") do
37
+ TIMES.times { PublicSuffixList.find(NAME_MEDIUM, ignore_private: true) != nil }
38
+ end
39
+ x.report("NAME_LONG") do
40
+ TIMES.times { PublicSuffixList.find(NAME_LONG) != nil }
41
+ end
42
+ x.report("NAME_LONG (noprivate)") do
43
+ TIMES.times { PublicSuffixList.find(NAME_LONG, ignore_private: true) != nil }
44
+ end
45
+ x.report("NAME_WILD") do
46
+ TIMES.times { PublicSuffixList.find(NAME_WILD) != nil }
47
+ end
48
+ x.report("NAME_WILD (noprivate)") do
49
+ TIMES.times { PublicSuffixList.find(NAME_WILD, ignore_private: true) != nil }
50
+ end
51
+ x.report("NAME_EXCP") do
52
+ TIMES.times { PublicSuffixList.find(NAME_EXCP) != nil }
53
+ end
54
+ x.report("NAME_EXCP (noprivate)") do
55
+ TIMES.times { PublicSuffixList.find(NAME_EXCP, ignore_private: true) != nil }
56
+ end
57
+
58
+ x.report("IAAA") do
59
+ TIMES.times { PublicSuffixList.find(IAAA) != nil }
60
+ end
61
+ x.report("IAAA (noprivate)") do
62
+ TIMES.times { PublicSuffixList.find(IAAA, ignore_private: true) != nil }
63
+ end
64
+ x.report("IZZZ") do
65
+ TIMES.times { PublicSuffixList.find(IZZZ) != nil }
66
+ end
67
+ x.report("IZZZ (noprivate)") do
68
+ TIMES.times { PublicSuffixList.find(IZZZ, ignore_private: true) != nil }
69
+ end
70
+
71
+ x.report("PAAA") do
72
+ TIMES.times { PublicSuffixList.find(PAAA) != nil }
73
+ end
74
+ x.report("PAAA (noprivate)") do
75
+ TIMES.times { PublicSuffixList.find(PAAA, ignore_private: true) != nil }
76
+ end
77
+ x.report("PZZZ") do
78
+ TIMES.times { PublicSuffixList.find(PZZZ) != nil }
79
+ end
80
+ x.report("PZZZ (noprivate)") do
81
+ TIMES.times { PublicSuffixList.find(PZZZ, ignore_private: true) != nil }
82
+ end
83
+
84
+ x.report("JP") do
85
+ TIMES.times { PublicSuffixList.find(JP) != nil }
86
+ end
87
+ x.report("JP (noprivate)") do
88
+ TIMES.times { PublicSuffixList.find(JP, ignore_private: true) != nil }
89
+ end
90
+ x.report("IT") do
91
+ TIMES.times { PublicSuffixList.find(IT) != nil }
92
+ end
93
+ x.report("IT (noprivate)") do
94
+ TIMES.times { PublicSuffixList.find(IT, ignore_private: true) != nil }
95
+ end
96
+ x.report("COM") do
97
+ TIMES.times { PublicSuffixList.find(COM) != nil }
98
+ end
99
+ x.report("COM (noprivate)") do
100
+ TIMES.times { PublicSuffixList.find(COM, ignore_private: true) != nil }
101
+ end
102
+ end
@@ -0,0 +1,91 @@
1
+ require 'benchmark/ips'
2
+
3
+ STRING = "www.subdomain.example.com"
4
+ ARRAY = %w(
5
+ com
6
+ example.com
7
+ subdomain.example.com
8
+ www.subdomain.example.com
9
+ )
10
+
11
+ def tokenizer1(string)
12
+ parts = string.split(".").reverse!
13
+ index = 0
14
+ query = parts[index]
15
+ names = []
16
+
17
+ loop do
18
+ names << query
19
+
20
+ index += 1
21
+ break if index >= parts.size
22
+ query = parts[index] + "." + query
23
+ end
24
+ names
25
+ end
26
+
27
+ def tokenizer2(string)
28
+ parts = string.split(".")
29
+ index = parts.size - 1
30
+ query = parts[index]
31
+ names = []
32
+
33
+ loop do
34
+ names << query
35
+
36
+ index -= 1
37
+ break if index < 0
38
+ query = parts[index] + "." + query
39
+ end
40
+ names
41
+ end
42
+
43
+ def tokenizer3(string)
44
+ isx = string.size
45
+ idx = string.size - 1
46
+ names = []
47
+
48
+ loop do
49
+ isx = string.rindex(".", isx - 1) || -1
50
+ names << string[isx + 1, idx - isx]
51
+
52
+ break if isx <= 0
53
+ end
54
+ names
55
+ end
56
+
57
+ def tokenizer4(string)
58
+ isx = string.size
59
+ idx = string.size - 1
60
+ names = []
61
+
62
+ loop do
63
+ isx = string.rindex(".", isx - 1) || -1
64
+ names << string[(isx+1)..idx]
65
+
66
+ break if isx <= 0
67
+ end
68
+ names
69
+ end
70
+
71
+ (x = tokenizer1(STRING)) == ARRAY or fail("tokenizer1 failed: #{x.inspect}")
72
+ (x = tokenizer2(STRING)) == ARRAY or fail("tokenizer2 failed: #{x.inspect}")
73
+ (x = tokenizer3(STRING)) == ARRAY or fail("tokenizer3 failed: #{x.inspect}")
74
+ (x = tokenizer4(STRING)) == ARRAY or fail("tokenizer4 failed: #{x.inspect}")
75
+
76
+ Benchmark.ips do |x|
77
+ x.report("tokenizer1") do
78
+ tokenizer1(STRING).is_a?(Array)
79
+ end
80
+ x.report("tokenizer2") do
81
+ tokenizer2(STRING).is_a?(Array)
82
+ end
83
+ x.report("tokenizer3") do
84
+ tokenizer3(STRING).is_a?(Array)
85
+ end
86
+ x.report("tokenizer4") do
87
+ tokenizer4(STRING).is_a?(Array)
88
+ end
89
+
90
+ x.compare!
91
+ end
@@ -0,0 +1,26 @@
1
+ require 'benchmark'
2
+ require_relative "../../lib/public_suffix"
3
+
4
+ JP = "www.yokoshibahikari.chiba.jp"
5
+
6
+ TIMES = (ARGV.first || 50_000).to_i
7
+
8
+ # Initialize
9
+ class PublicSuffix::List
10
+ public :select
11
+ end
12
+ PublicSuffixList = PublicSuffix::List.default
13
+ PublicSuffixList.select("example.jp")
14
+ PublicSuffixList.find("example.jp")
15
+
16
+ Benchmark.bmbm(25) do |x|
17
+ x.report("JP select") do
18
+ TIMES.times { PublicSuffixList.select(JP) }
19
+ end
20
+ x.report("JP find") do
21
+ TIMES.times { PublicSuffixList.find(JP) }
22
+ end
23
+ # x.report("JP (noprivate)") do
24
+ # TIMES.times { PublicSuffixList.find(JP, ignore_private: true) != nil }
25
+ # end
26
+ end
@@ -0,0 +1,25 @@
1
+ require 'benchmark'
2
+ require_relative "../../lib/public_suffix"
3
+
4
+ JP = "www.yokoshibahikari.chiba.jp"
5
+
6
+ TIMES = (ARGV.first || 50_000).to_i
7
+
8
+ # Initialize
9
+ class PublicSuffix::List
10
+ public :select
11
+ end
12
+ PublicSuffixList = PublicSuffix::List.default
13
+ PublicSuffixList.select("example.jp")
14
+
15
+ Benchmark.bmbm(25) do |x|
16
+ x.report("select jp") do
17
+ TIMES.times { PublicSuffixList.select("jp") }
18
+ end
19
+ x.report("select example.jp") do
20
+ TIMES.times { PublicSuffixList.select("example.jp") }
21
+ end
22
+ x.report("select www.example.jp") do
23
+ TIMES.times { PublicSuffixList.select("www.example.jp") }
24
+ end
25
+ end