RSpec.describe Relaton::Db do
before(:each) do |example|
# Relaton.instance_variable_set :@configuration, nil
FileUtils.rm_rf %w[testcache testcache2]
if example.metadata[:vcr]
# Force to download index file
require "relaton/index"
allow_any_instance_of(Relaton::Index::Type).to receive(:actual?).and_return(false)
allow_any_instance_of(Relaton::Index::FileIO).to receive(:check_file).and_return(nil)
end
end
subject { Relaton::Db.new nil, nil }
context "instance methods" do
context "#search_edition_year" do
it "create bibitem from YAML content" do
h = { "docid" => [{ "id" => "ISO 123", type: "ISO", "primary" => true }] }
expect(YAML).to receive(:safe_load).with(:content).and_return h
allow(YAML).to receive(:safe_load).and_call_original
item = subject.send :search_edition_year, "iso/item.yaml", :content, nil, nil
expect(item).to be_instance_of RelatonIsoBib::IsoBibliographicItem
end
end
context "#new_bib_entry" do
let(:db) { double "db" }
before do
expect(db).to receive(:[]).with("ISO(ISO 123)").and_return "not_found"
end
it "warn if cached entry is not_found" do
expect do
expect(subject).to_not receive(:fetch_entry)
entry = subject.send :new_bib_entry, "ISO 123", nil, {}, :relaton_iso, db: db, id: "ISO(ISO 123)"
expect(entry).to be_nil
end.to output("[relaton] INFO: (ISO 123) not found in cache, if you wish " \
"to ignore cache please use `no-cache` option.\n").to_stderr_from_any_process
end
it "ignore cache" do
expect(subject).to receive(:fetch_entry).with(
"ISO 123", nil, { no_cache: true }, :relaton_iso, db: db, id: "ISO(ISO 123)",
).and_return :entry
entry = subject.send(
:new_bib_entry, "ISO 123", nil, { no_cache: true }, :relaton_iso, db: db, id: "ISO(ISO 123)"
)
expect(entry).to be :entry
end
end
context "#combine_doc" do
it "retrun nil for BIPM documents" do
code = double "code"
expect(code).not_to receive(:split)
expect(subject.send(:combine_doc, code, nil, {}, :relaton_bipm)).to be_nil
end
end
context "#fetch_entry" do
let(:db_cache) { double "db_cache" }
before do
expect(subject).to receive(:net_retry).with("ISO 123", nil, {}, kind_of(RelatonIso::Processor), 1).and_return :bib
end
it "using cache" do
expect(db_cache).to receive(:[]).with("ISO(ISO 123)").and_return nil
expect(db_cache).to receive(:[]=).with("ISO(ISO 123)", :entry)
expect(subject).to receive(:check_entry).with(:bib, :relaton_iso, db: db_cache, id: "ISO(ISO 123)").and_return :entry
entry = subject.send :fetch_entry, "ISO 123", nil, {}, :relaton_iso, db: db_cache, id: "ISO(ISO 123)"
expect(entry).to be :entry
end
it "DbCache is undefined" do
expect(subject).to receive(:check_entry).with(:bib, :relaton_iso, **{}).and_return :entry
entry = subject.send :fetch_entry, "ISO 123", nil, {}, :relaton_iso
expect(entry).to be :entry
end
it "not using cache" do
expect(subject).to receive(:bib_entry).with(:bib).and_return :entry
expect(subject).to receive(:check_entry).with(
:bib, :relaton_iso, db: db_cache, id: "ISO(ISO 123)", no_cache: true
).and_return :entry
expect(db_cache).to receive(:[]).with("ISO(ISO 123)").and_return :entry
entry = subject.send :fetch_entry, "ISO 123", nil, {}, :relaton_iso, db: db_cache, id: "ISO(ISO 123)", no_cache: true
expect(entry).to be :entry
end
end
end
context "class methods" do
it "::init_bib_caches" do
expect(FileUtils).to receive(:rm_rf).with(/\/\.relaton\/cache$/)
expect(FileUtils).to receive(:rm_rf).with(/testcache\/cache$/)
expect(Relaton::Db).to receive(:new).with(/\/\.relaton\/cache$/, /testcache\/cache$/)
Relaton::Db.init_bib_caches(global_cache: true, local_cache: "testcache", flush_caches: true)
end
end
context "modifing database" do
let(:db) { Relaton::Db.new "testcache", "testcache2" }
before(:each) do
db.save_entry "ISO(ISO 123)", "
The first test22011-10-12
DOC
db.save_entry "IEC(IEC 123)", <<~DOC
The second test12015-12
DOC
end
after(:each) { db.clear }
it "one document" do
item = db.fetch_db "ISO((ISO 124)"
expect(item).to be_nil
item = db.fetch_db "ISO(ISO 123)"
expect(item).to be_instance_of RelatonIsoBib::IsoBibliographicItem
end
it "all documents" do
items = db.fetch_all
expect(items.size).to be 2
expect(items[0]).to be_instance_of RelatonIec::IecBibliographicItem
expect(items[1]).to be_instance_of RelatonIsoBib::IsoBibliographicItem
end
context "search for text" do
it do
items = db.fetch_all "test"
expect(items.size).to eq 2
items = db.fetch_all "first"
expect(items.size).to eq 1
expect(items[0].id).to eq "ISO123"
end
it "in attributes" do
items = db.fetch_all "123"
expect(items.size).to eq 2
items = db.fetch_all "ISO"
expect(items.size).to eq 1
expect(items[0].id).to eq "ISO123"
end
it "and fail" do
items = db.fetch_all "bibitem"
expect(items.size).to eq 0
end
it "and edition" do
items = db.fetch_all "123", edition: "2"
expect(items.size).to eq 1
expect(items[0].id).to eq "ISO123"
end
it "and year" do
items = db.fetch_all "123", year: 2015
expect(items.size).to eq 1
expect(items[0].id).to eq "IEC123"
end
end
end
it "returns docid type" do
db = Relaton::Db.new "testcache", "testcache2"
expect(db.docid_type("CN(GB/T 1.1)")).to eq ["Chinese Standard", "GB/T 1.1"]
end
context "#fetch" do
it "doesn't use cache" do
docid = RelatonBib::DocumentIdentifier.new id: "ISO 19115-1", type: "ISO"
item = RelatonIsoBib::IsoBibliographicItem.new docid: [docid]
expect(RelatonIso::IsoBibliography).to receive(:get).with("ISO 19115-1", nil, {}).and_return item
bib = subject.fetch("ISO 19115-1", nil, {})
expect(bib).to be_instance_of RelatonIsoBib::IsoBibliographicItem
end
it "when no local db", vcr: "iso_19115_1" do
db = Relaton::Db.new "testcache", nil
bib = db.fetch("ISO 19115-1", nil, {})
expect(bib).to be_instance_of RelatonIsoBib::IsoBibliographicItem
end
it "document with net retries" do
expect(subject.instance_variable_get(:@registry).processors[:relaton_ietf]).to receive(:get)
.and_raise(RelatonBib::RequestError).exactly(3).times
expect { subject.fetch "RFC 8341", nil, retries: 3 }.to raise_error RelatonBib::RequestError
end
it "strip reference" do
expect(subject).to receive(:combine_doc).with("ISO 19115-1", nil, {}, :relaton_iso).and_return :doc
expect(subject.fetch(" ISO 19115-1 ", nil, {})).to be :doc
end
end
it "fetch std", vcr: "iso_19115_1_std" do
db = Relaton::Db.new "testcache", nil
bib = db.fetch_std("ISO 19115-1", nil, :relaton_iso, {})
expect(bib).to be_instance_of RelatonIsoBib::IsoBibliographicItem
end
context "async fetch" do
let(:queue) { Queue.new }
it "success" do
refs = ["ITU-T G.993.5", "ITU-T G.994.1", "ITU-T H.264.1", "ITU-T H.740",
"ITU-T Y.1911", "ITU-T Y.2012", "ITU-T Y.2206", "ITU-T O.172",
"ITU-T G.780/Y.1351", "ITU-T G.711", "ITU-T G.1011"]
results = []
refs.each do |ref|
expect(subject).to receive(:fetch).with(ref, nil, {}).and_return :result
subject.fetch_async(ref) { |r| queue << [r, ref] }
end
Timeout.timeout(60) { refs.size.times { results << queue.pop } }
results.each do |result|
expect(result[0]).to be :result
end
end
it "BIPM i18n" do
refs = ["CGPM -- Resolution (1889)", "CGPM -- RĂ©solution (1889)",
"CGPM -- RĂ©union 9 (1948)", "CGPM -- Meeting 9 (1948)"]
results = []
refs.each do |ref|
expect(subject).to receive(:fetch).with(ref, nil, {}).and_return :result
subject.fetch_async(ref) { |r| queue << [r, ref] }
end
Timeout.timeout(60) { refs.size.times { results << queue.pop } }
results.each do |result|
expect(result[0]).to be :result
end
end
it "prefix not found", vcr: "rfc_unsuccess" do
result = ""
subject.fetch_async("ABC 123456") { |r| queue << r }
Timeout.timeout(5) { result = queue.pop }
expect(result).to be_nil
end
it "handle HTTP request error" do
expect(subject).to receive(:fetch).and_raise RelatonBib::RequestError
subject.fetch_async("ISO REF") { |r| queue << r }
result = Timeout.timeout(5) { queue.pop }
expect(result).to be_instance_of RelatonBib::RequestError
end
it "handle other errors" do
expect(subject).to receive(:fetch).and_raise Errno::EACCES
log_io = Relaton.logger_pool[:default].instance_variable_get(:@logdev)
expect(log_io).to receive(:write).with("[relaton] ERROR: `ISO REF` -- Permission denied\n")
subject.fetch_async("ISO REF") { |r| queue << r }
result = Timeout.timeout(5) { queue.pop }
expect(result).to be_nil
end
it "use threads number from RELATON_FETCH_PARALLEL" do
expect(ENV).to receive(:[]).with("RELATON_FETCH_PARALLEL").and_return(1)
allow(ENV).to receive(:[]).and_call_original
expect(Relaton::WorkersPool).to receive(:new).with(1).and_call_original
expect(subject).to receive(:fetch).with("ITU-T G.993.5", nil, {})
subject.fetch_async("ITU-T G.993.5") { |r| queue << r }
Timeout.timeout(50) { queue.pop }
end
end
end