dodb.cr/spec/cached.cr

391 lines
9.1 KiB
Crystal
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

require "spec"
require "file_utils"
require "../src/dodb.cr"
require "./test-data.cr"
class DODB::SpecDataBase < DODB::DataBase::Cached(Ship)
def initialize(storage_ext = "", remove_previous_data = true)
storage_dir = "test-storage#{storage_ext}"
if remove_previous_data
::FileUtils.rm_rf storage_dir
end
super storage_dir
end
end
describe "DODB::DataBase::Cached" do
describe "basics" do
it "store and get data" do
db = DODB::SpecDataBase.new
Ship.all_ships.each do |ship|
db << ship
end
db.to_a.sort.should eq(Ship.all_ships.sort)
end
it "rewrite already stored data" do
db = DODB::SpecDataBase.new
ship = Ship.all_ships[0]
key = db << ship
db[key] = Ship.new "broken"
db[key] = ship
db[key].should eq(ship)
end
it "properly remove data" do
db = DODB::SpecDataBase.new
Ship.all_ships.each do |ship|
db << ship
end
Ship.all_ships.each do |ship|
db.pop
end
Ship.all_ships.each_with_index do |ship, i|
# FIXME: Should it raise a particular exception?
expect_raises DODB::MissingEntry do
db[i]
end
db[i]?.should be_nil
end
end
it "iterates in normal and reversed order" do
db = DODB::SpecDataBase.new
Ship.all_ships.each do |ship|
db << ship
end
# The two #each test iteration.
db.each_with_index do |item, index|
item.should eq Ship.all_ships[index]
end
db.each_with_index(reversed: true) do |item, index|
item.should eq Ship.all_ships[index]
end
# Actual reversal is tested here.
db.to_a(reversed: true).should eq db.to_a.reverse
end
it "respects the provided offsets if any" do
db = DODB::SpecDataBase.new
Ship.all_ships.each do |ship|
db << ship
end
db.to_a(start_offset: 0, end_offset: 0)[0]?.should eq Ship.mutsuki
db.to_a(start_offset: 1, end_offset: 1)[0]?.should eq Ship.kisaragi
db.to_a(start_offset: 2, end_offset: 2)[0]?.should eq Ship.yayoi
db.to_a(start_offset: 0, end_offset: 2).should eq [
Ship.mutsuki, Ship.kisaragi, Ship.yayoi
]
end
end
# describe "indices" do
# it "do basic indexing" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# Ship.all_ships.each_with_index do |ship|
# db_ships_by_name.get?(ship.name).should eq(ship)
# end
# end
# end
# it "raise on index overload" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
#
# db << Ship.kisaragi
#
# # Should not be allowed to store an entry whose “name” field
# # already exists.
# expect_raises(DODB::IndexOverload) do
# db << Ship.kisaragi
# end
# end
#
# it "properly deindex" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# Ship.all_ships.each_with_index do |ship, i|
# db.delete i
# end
#
# Ship.all_ships.each do |ship|
# db_ships_by_name.get?(ship.name).should be_nil
# end
# end
#
# it "properly reindex" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
#
# key = db << Ship.kisaragi
#
# # We give the old id to the new ship, to get it replaced in
# # the database.
# some_new_ship = Ship.all_ships[2].clone
#
# db[key] = some_new_ship
#
# db[key].should eq(some_new_ship)
#
# db_ships_by_name.get?(some_new_ship.name).should eq(some_new_ship)
# end
#
# it "properly updates" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# new_kisaragi = Ship.kisaragi.clone.tap do |s|
# s.name = "Kisaragi Kai" # Dont think about it too much.
# end
#
# # Were changing an indexed value on purpose.
# db_ships_by_name.update "Kisaragi", new_kisaragi
#
# db_ships_by_name.get?("Kisaragi").should be_nil
# db_ships_by_name.get?(new_kisaragi.name).should eq new_kisaragi
# end
# end
#
# describe "partitions" do
# it "do basic partitioning" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_class = db.new_partition "class", &.klass
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# Ship.all_ships.each do |ship|
# db_ships_by_class.get(ship.klass).should contain(ship)
# end
#
# # We extract the possible classes to do test on them.
# ship_classes = Ship.all_ships.map(&.klass).uniq
# ship_classes.each do |klass|
# partition = db_ships_by_class.get klass
#
# # A partition on “class” should contain entries that all
# # share the same value of “class”.
# partition.map(&.klass.==(klass)).reduce { |a, b|
# a && b
# }.should be_true
# end
#
# db_ships_by_class.get("does-not-exist").should eq [] of Ship
# end
#
# it "removes select elements from partitions" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_class = db.new_partition "class", &.klass
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# db_ships_by_class.delete "Mutsuki", &.name.==("Kisaragi")
#
# Ship.all_ships.map(&.klass).uniq.each do |klass|
# partition = db_ships_by_class.get klass
#
# partition.any?(&.name.==("Kisaragi")).should be_false
# end
# end
# end
#
# describe "tags" do
# it "do basic tagging" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_tags = db.new_tags "tags", &.tags
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# db_ships_by_tags.get("flagship").should eq([Ship.flagship])
#
# # All returned entries should have the requested tag.
# db_ships_by_tags.get("name ship")
# .map(&.tags.includes?("name ship"))
# .reduce { |a, e| a && e }
# .should be_true
#
# # There shouldnt be one in our data about WWII Japanese warships…
# db_ships_by_tags.get("starship").should eq([] of Ship)
# end
#
# it "properly removes tags" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_tags = db.new_tags "tags", &.tags
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# # Removing the “flagship” tag, brace for impact.
# flagship, index = db_ships_by_tags.get_with_indices("flagship")[0]
# flagship.tags = [] of String
# db[index] = flagship
#
#
#
## ship, index = db_ships_by_tags.update(tag: "flagship") do |ship, index|
## ship.tags = [] of String
## db[index] = ship
## end
#
# db_ships_by_tags.get("flagship").should eq([] of Ship)
# end
#
# it "gets items that have multiple tags" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_tags = db.new_tags "tags", &.tags
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# results = db_ships_by_tags.get(["flagship", "name ship"])
# results.should eq([Ship.yamato])
#
# results = db_ships_by_tags.get(["name ship", "flagship"])
# results.should eq([Ship.yamato])
#
# results = db_ships_by_tags.get(["flagship"])
# results.should eq([Ship.yamato])
# end
# end
#
# describe "atomic operations" do
# it "safe_get and safe_get?" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# Ship.all_ships.each do |ship|
# db_ships_by_name.safe_get ship.name do |results|
# results.should eq(ship)
# end
#
# db_ships_by_name.safe_get? ship.name do |results|
# results.should eq(ship)
# end
# end
# end
# end
#
# describe "tools" do
# it "rebuilds indexes" do
# db = DODB::SpecDataBase.new
#
# db_ships_by_name = db.new_index "name", &.name
# db_ships_by_class = db.new_partition "class", &.klass
# db_ships_by_tags = db.new_tags "tags", &.tags
#
# Ship.all_ships.each do |ship|
# db << ship
# end
#
# db.reindex_everything!
#
# Ship.all_ships.each do |ship|
# db_ships_by_name.get?(ship.name).should eq(ship)
# db_ships_by_class.get(ship.klass).should contain(ship)
# end
# end
#
# it "migrates properly" do
# ::FileUtils.rm_rf "test-storage-migration-origin"
# old_db = DODB::DataBase(PrimitiveShip).new "test-storage-migration-origin"
#
# old_ships_by_name = old_db.new_index "name", &.name
# old_ships_by_class = old_db.new_partition "class", &.class_name
#
# PrimitiveShip.all_ships.each do |ship|
# old_db << ship
# end
#
# # At this point, the “old” DB is filled. Now we need to convert
# # to the new DB.
#
# new_db = DODB::SpecDataBase.new "-migration-target"
#
# new_ships_by_name = new_db.new_index "name", &.name
# new_ships_by_class = new_db.new_partition "class", &.klass
# new_ships_by_tags = new_db.new_tags "tags", &.tags
#
# old_db.each_with_index do |ship, index|
# new_ship = Ship.new ship.name,
# klass: ship.class_name,
# id: ship.id,
# tags: Array(String).new.tap { |tags|
# tags << "name ship" if ship.name == ship.class_name
# }
#
# new_db[index] = new_ship
# end
#
# # At this point, the conversion is done, so… were making a few
# # arbitrary tests on the new data.
#
# old_db.each_with_index do |old_ship, old_index|
# ship = new_db[old_index]
#
# ship.id.should eq(old_ship.id)
# ship.klass.should eq(old_ship.class_name)
#
# ship.tags.any?(&.==("name ship")).should be_true if ship.name == ship.klass
# end
# end
# end
end