public_suffix 2.0.5 → 4.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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