1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
|
# frozen_string_literal: true
require "helper"
class TestCssCacheAccess < Nokogiri::TestCase
def setup
super
@css = "a1 > b2 > c3"
Nokogiri::CSS::Parser.clear_cache
Nokogiri::CSS::Parser.class_eval do
class << @cache
alias_method :old_bracket, :[]
def access_count
@access_count ||= 0
end
def [](key)
@access_count ||= 0
@access_count += 1
old_bracket(key)
end
end
end
assert_predicate(Nokogiri::CSS::Parser, :cache_on?)
end
def teardown
Nokogiri::CSS::Parser.clear_cache(true)
Nokogiri::CSS::Parser.set_cache(true)
super
end
[false, true].each do |cache_setting|
define_method "test_css_cache_#{cache_setting ? "true" : "false"}" do
Nokogiri::CSS::Parser.set_cache(cache_setting)
Nokogiri::CSS.xpath_for(@css)
Nokogiri::CSS.xpath_for(@css)
Nokogiri::CSS::Parser.new.xpath_for(@css, "//", Nokogiri::CSS::XPathVisitor.new)
Nokogiri::CSS::Parser.new.xpath_for(@css, "//", Nokogiri::CSS::XPathVisitor.new)
if cache_setting
assert_equal(1, Nokogiri::CSS::Parser.class_eval { @cache.count })
assert_equal(4, Nokogiri::CSS::Parser.class_eval { @cache.access_count })
else
assert_equal(0, Nokogiri::CSS::Parser.class_eval { @cache.count })
assert_equal(0, Nokogiri::CSS::Parser.class_eval { @cache.access_count })
end
end
end
end
class TestCssCache < Nokogiri::TestCase
def teardown
Nokogiri::CSS::Parser.set_cache(true)
super
end
def test_enabled_cache_is_used
Nokogiri::CSS::Parser.clear_cache
Nokogiri::CSS::Parser.set_cache(true)
css = ".foo .bar .baz"
cache = Nokogiri::CSS::Parser.instance_variable_get("@cache")
assert_empty(cache)
Nokogiri::CSS.xpath_for(css)
refute_empty(cache)
key = cache.keys.first
cache[key] = "this is an injected value"
assert_equal("this is an injected value", Nokogiri::CSS.xpath_for(css))
end
def test_disabled_cache_is_not_used
Nokogiri::CSS::Parser.clear_cache
Nokogiri::CSS::Parser.set_cache(false)
css = ".foo .bar .baz"
cache = Nokogiri::CSS::Parser.instance_variable_get("@cache")
assert_empty(cache)
Nokogiri::CSS.xpath_for(css)
assert_empty(cache)
end
def test_without_cache_avoids_cache
Nokogiri::CSS::Parser.clear_cache
Nokogiri::CSS::Parser.set_cache(true)
css = ".foo .bar .baz"
cache = Nokogiri::CSS::Parser.instance_variable_get("@cache")
assert_empty(cache)
Nokogiri::CSS::Parser.without_cache do
Nokogiri::CSS.xpath_for(css)
end
assert_empty(cache)
end
def test_without_cache_resets_cache_value
Nokogiri::CSS::Parser.set_cache(true)
Nokogiri::CSS::Parser.without_cache do
refute_predicate(Nokogiri::CSS::Parser, :cache_on?)
end
assert_predicate(Nokogiri::CSS::Parser, :cache_on?)
end
def test_without_cache_resets_cache_value_even_after_exception
Nokogiri::CSS::Parser.set_cache(true)
assert_raises(RuntimeError) do
Nokogiri::CSS::Parser.without_cache do
raise RuntimeError
end
end
assert_predicate(Nokogiri::CSS::Parser, :cache_on?)
end
def test_cache_key_on_ns_prefix_and_visitor_config
Nokogiri::CSS::Parser.clear_cache
Nokogiri::CSS::Parser.set_cache(true)
cache = Nokogiri::CSS::Parser.instance_variable_get("@cache")
assert_empty(cache)
Nokogiri::CSS.xpath_for("foo")
Nokogiri::CSS.xpath_for("foo", prefix: ".//")
Nokogiri::CSS.xpath_for("foo", prefix: ".//", ns: { "example" => "http://example.com/" })
Nokogiri::CSS.xpath_for("foo", prefix: ".//", ns: { "example" => "http://example.com/" },
visitor: Nokogiri::CSS::XPathVisitor.new(builtins: Nokogiri::CSS::XPathVisitor::BuiltinsConfig::ALWAYS))
Nokogiri::CSS.xpath_for("foo", prefix: ".//", ns: { "example" => "http://example.com/" },
visitor: Nokogiri::CSS::XPathVisitor.new(builtins: Nokogiri::CSS::XPathVisitor::BuiltinsConfig::ALWAYS,
doctype: Nokogiri::CSS::XPathVisitor::DoctypeConfig::HTML5))
assert_equal(5, cache.length)
end
def test_race_condition
# https://github.com/sparklemotion/nokogiri/issues/1935
threads = []
Nokogiri::CSS::Parser.set_cache(true)
threads << Thread.new do
Nokogiri::CSS::Parser.without_cache do
sleep(0.02)
end
end
threads << Thread.new do
sleep(0.01)
Nokogiri::CSS::Parser.without_cache do
sleep(0.02)
end
end
threads.each(&:join)
assert_predicate(Nokogiri::CSS::Parser, :cache_on?)
end
end
|