#!/usr/bin/env ruby -w
require "test/unit"
require "xamplr-generator"
include XamplGenerator
include Xampl
def assert_xampl_exception(name)
xampl_exception = assert_raise(XamplException){
yield
}
assert_equal(name, xampl_exception.name)
end
options = Xampl.make(Options) { | options |
options.new_index_attribute("name")
options.new_index_attribute("id")
options.new_index_attribute("pid").persisted = true
options.resolve("http://xampl.com/example", "XamplExample", "ex")
options.resolve("http://xampl.com/example/special", "XamplExampleSpecial", "exs")
}
generator = Generator.new(options)
the_xml_file = File.join(".", "xml", "example.xml")
if (0 < ARGV.size) then
File.open(the_xml_file){ | f |
s = f.read
generator.comprehend_from_strings([s])
generator.generate_and_eval() { | module_definition, name |
eval(module_definition, nil, name, 1)
}
#generator.print_stats
}
include XamplExample
else
generator.comprehend_from_files([the_xml_file])
generator.generate_to_directory(File.join(".", "tmp"))
#generator.print_stats
require "tmp/XamplExample"
include XamplExample
end
#generator.report_elements
class TestXampl < Test::Unit::TestCase
def setup
Xampl.disable_all_persisters
#FromXML.reset_registry
end
def test_simple_xampl
emph1 = Emph.new
assert_not_nil(emph1.is_changed)
emph2 = Emph.new
assert_not_nil(emph2.is_changed)
emph3 = Emph.new
assert_not_nil(emph3.is_changed)
emph1.content = "emph 1"
assert_not_nil(emph1.is_changed)
emph2.content = "emph 2"
assert_not_nil(emph2.is_changed)
assert_equal("emph 1", emph1.content)
assert_equal("emph 2", emph2.content)
assert_equal("emph 1", emph1.test_to_xml)
assert_equal("emph 2", emph2.test_to_xml)
assert_equal("", emph3.test_to_xml)
fakeRules = XMLPrinter.new("fake...")
emph1.test_to_xml_internal(fakeRules)
r = fakeRules.done
assert_equal("fake... xmlns:ex='http://xampl.com/example'emph 1", r)
assert_not_nil(emph1.is_changed)
assert_not_nil(emph2.is_changed)
assert_not_nil(emph3.is_changed)
check_parents(emph1)
check_parents(emph2)
check_parents(emph3)
end
def test_empty_xampl
stuff1 = Stuff.new
assert_not_nil(stuff1.is_changed)
stuff1.kind = 'test'
assert_not_nil(stuff1.is_changed)
stuff2 = Stuff.new
assert_not_nil(stuff2.is_changed)
stuff3 = Stuff.new
assert_not_nil(stuff3.is_changed)
stuff3.kind = 'test'
assert_not_nil(stuff3.is_changed)
stuff3.special = 'test'
assert_not_nil(stuff3.is_changed)
assert_equal("",
stuff1.test_to_xml)
assert_equal("",
stuff2.test_to_xml)
assert_equal("",
stuff3.test_to_xml)
fakeRules = XMLPrinter.new("fake...")
stuff1.test_to_xml_internal(fakeRules)
r = fakeRules.done
assert_equal("fake... xmlns:ex='http://xampl.com/example' xmlns:exs='http://xampl.com/example/special'", r)
check_parents(stuff1)
check_parents(stuff2)
check_parents(stuff3)
end
def test_mixed_xampl
desc1 = Description.new
assert_not_nil(desc1.is_changed)
desc1.kind = "desc1"
assert_not_nil(desc1.is_changed)
assert_equal("",
desc1.test_to_xml)
desc1.add_content("hello ")
emph_content_1 = "there"
desc1.new_emph.content = emph_content_1
desc1.add_content("! How ")
emph_content_2 = "are"
desc1.new_emph.content = emph_content_2
desc1.add_content(" you?")
assert_not_nil(desc1.is_changed)
assert_equal("hello there! How are you?",
desc1.test_to_xml)
assert_equal(desc1.emph_child.length, 2)
assert_equal(emph_content_1, desc1.emph_child[0].content, emph_content_1)
assert_equal(emph_content_2, desc1.emph_child[1].content, emph_content_2)
check_parents(desc1)
end
def test_data_xampl
emph_content_1 = "there"
emph_content_2 = "are"
big_thing = Xampl.make(Thing){ | big_thing |
big_thing.pid = "big_thing"
big_thing.new_thing("thing"){ | thing |
thing.new_stuff.kind = "stuff1"
thing.new_description{ | desc |
desc.kind = "desc1"
desc.add_content("hello ")
desc.new_emph.content = emph_content_1
desc.add_content("! How ")
desc.new_emph.content = emph_content_2
desc.add_content(" you?")
}
}
}
### desc1 = Description.new
### desc1.kind = "desc1"
###
### desc1.add_content("hello ")
### emph_content_1 = "there"
### desc1.new_emph.content = emph_content_1
### desc1.add_content("! How ")
### emph_content_2 = "are"
### desc1.new_emph.content = emph_content_2
### desc1.add_content(" you?")
###
### thing = Thing.new
### thing.pid = "thing"
### assert(thing.is_changed)
### thing.new_stuff.kind = "stuff1"
### assert_not_nil(thing.is_changed)
### thing.is_changed = nil
### thing.add_description(desc1)
### assert_not_nil(thing.is_changed)
###
### big_thing = Thing.new
### big_thing.add_thing(thing)
assert_equal("hello there! How are you?",
big_thing.test_to_xml)
assert_equal(1, big_thing.children.length)
assert_equal(2, big_thing.thing_child[0].children.length)
assert_equal(big_thing.thing_child[0].description_child[0].emph_child.length, 2)
assert_equal(emph_content_1, big_thing.thing_child[0].description_child[0].emph_child[0].content, emph_content_1)
assert_equal(emph_content_2, big_thing.thing_child[0].description_child[0].emph_child[1].content, emph_content_2)
check_parents(big_thing)
end
def test_ensure
big_thing = Xampl.make(Thing){ | big_thing |
big_thing.pid = "big_thing"
big_thing.ensure_thing("thing"){ | thing |
thing.info = "first";
}
big_thing.ensure_thing("thing"){ | thing |
flunk "What are you doing in here?"
thing.info = "second";
}
}
assert_equal(1, big_thing.thing.length)
assert_equal("first", big_thing.thing[0].info)
desc = Description.new
desc.ensure_emph
assert_equal(1, desc.emph.length)
#NOTE -- ensure_emph used to be aliased to new_emph, now it just makes
# sure that there is at least one emph
end
def test_data_xampl_using_append
emph_content_1 = "there"
emph1 = Emph.new
emph1 << emph_content_1
emph_content_2 = "are"
emph2 = Emph.new
emph2.content = emph_content_2
desc1 = Description.new
desc1.kind = "desc1"
desc1.is_changed = nil
desc1 << "hello " << emph1 << "! How " << emph2 << " you?"
assert_not_nil(desc1.is_changed)
thing = Thing.new
thing.pid = "thing"
thing.new_stuff.kind = "stuff1"
thing << desc1
big_thing = Thing.new
big_thing << thing
assert_equal("hello there! How are you?",
big_thing.test_to_xml)
assert_equal(2, big_thing.thing_child[0].description_child[0].emph_child.length)
assert_equal(emph_content_1, big_thing.thing_child[0].description_child[0].emph_child[0].content)
assert_equal(emph_content_2, big_thing.thing_child[0].description_child[0].emph_child[1].content)
check_parents(big_thing)
end
def test_from_xml
emph_content_1 = "there"
emph1 = Emph.new
emph1 << emph_content_1
emph_content_2 = "are"
emph2 = Emph.new
emph2.content = emph_content_2
desc1 = Description.new
desc1.kind = "desc1"
desc1.is_changed = nil
desc1 << "hello " << emph1 << "! How " << emph2 << " you?"
thing = Thing.new
thing.pid = "thing"
thing.new_stuff.kind = "stuff1"
thing << desc1
big_thing = Thing.new
big_thing << "leading content" << thing << "trailing content"
#puts big_thing.test_to_xml
#pp = FromXML.new
#pp.setup_parse_string(big_thing.test_to_xml)
#while not pp.endDocument?
#event = pp.next_interesting_event
#puts event
#if (event == Xampl_PP::TEXT) then
#puts "TEXT [[[" << pp.text << "]]]"
#end
#end
pp = FromXML.new
pp.setup_parse_string(big_thing.test_to_xml)
assert_equal(pp.next_interesting_event, Xampl_PP::START_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::TEXT)
assert_equal(pp.next_interesting_event, Xampl_PP::START_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::START_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::START_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::TEXT)
assert_equal(pp.next_interesting_event, Xampl_PP::START_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::TEXT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::TEXT)
assert_equal(pp.next_interesting_event, Xampl_PP::START_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::TEXT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::TEXT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_ELEMENT)
assert_equal(pp.next_interesting_event, Xampl_PP::END_DOCUMENT)
assert(pp.endDocument?)
pp = FromXML.new
#another_big_thing = pp.parse_string(big_thing.test_to_xml)
another_big_thing = pp.parse_string(big_thing.pp_xml)
#assert_equal(big_thing.test_to_xml, another_big_thing.test_to_xml)
assert_equal(big_thing.pp_xml.gsub(/\s/, ''), another_big_thing.pp_xml.gsub(/\s/, ''))
assert_not_same(big_thing, another_big_thing)
end
def test_index
thing = Thing.new
thing.new_key_value("one").value = "1"
thing.new_key_value("two").value = "2"
assert_same(thing.key_value_child[0], thing.key_value_child["one"])
assert_same(thing.key_value_child[1], thing.key_value_child["two"])
thing.new_key_value("one").value = "1a"
assert_same(thing.key_value_child[0], thing.key_value_child["two"])
assert_same(thing.key_value_child[1], thing.key_value_child["one"])
check_parents(thing)
end
def test_indexed_remove
thing = Thing.new
thing.new_key_value("one").value = "1"
thing.remove_key_value(thing.key_value["one"])
assert_equal(0, thing.children.size)
assert_equal(0, thing.key_value_child.size)
thing = Thing.new
thing.new_key_value("one").value = "1"
thing.new_key_value("two").value = "2"
thing.remove_key_value(thing.key_value["one"])
assert_equal(1, thing.children.size)
assert_equal(1, thing.key_value_child.size)
assert_not_nil(thing.key_value["two"])
assert_equal("2", thing.key_value["two"].value)
end
def test_parents
thing = Thing.new
(kv1 = thing.new_key_value("one")).value = "1"
(kv2 = thing.new_key_value("two")).value = "2"
assert_same(thing, thing.key_value_child[0].parents[0])
assert_same(thing, thing.key_value_child[1].parents[0])
another_thing = Thing.new
another_thing << kv1 << kv2
assert_equal(2, kv1.parents.size)
assert_equal(2, kv2.parents.size)
check_parents(thing)
check_parents(another_thing)
end
def test_non_string_attributes
stuff1 = Stuff.new
stuff1.kind = 123.456
assert_equal("",
stuff1.test_to_xml)
stuff1.kind = nil
assert_equal("",
stuff1.test_to_xml)
stuff1.kind = [1, 2, 3]
assert_equal("",
stuff1.test_to_xml)
stuff2 = Stuff.new
stuff2.kind = 123
stuff1.kind = stuff2
assert_equal("",
stuff1.test_to_xml)
thing = Thing.new
thing.pid = "thing"
thing << stuff2
stuff1.kind = thing
assert_equal("",
stuff1.test_to_xml)
check_parents(stuff1)
end
def test_registry
assert_equal([ Emph ], FromXML::registered(Emph::ns_tag))
assert_equal([ Emph ], FromXML::registered(Emph::tag))
assert_equal([ Stuff ], FromXML::registered(Stuff::ns_tag))
assert_equal([ Stuff ], FromXML::registered(Stuff::tag))
FromXML::register(Emph::tag, Emph::ns_tag, Emph)
assert_equal([ Emph ], FromXML::registered(Emph::ns_tag))
assert_equal([ Emph ], FromXML::registered(Emph::tag))
FromXML::register(Emph::tag, Thing::ns_tag, Thing)
assert_equal([ Emph ], FromXML::registered(Emph::ns_tag))
assert_equal([ Emph, Thing ], FromXML::registered(Emph::tag))
end
def test_in_memory_persistence_basics
stuff = Stuff.new
thing = Thing.new
thing << stuff
assert(!stuff.persist_required)
assert(thing.persist_required)
assert(nil == thing.persister)
persister = InMemoryPersister.new
assert_xampl_exception(:no_index_so_no_persist){
persister.write(thing)
}
thing.pid = "thing"
assert(persister.write(thing))
saved_thing = persister.read(Thing, "thing")
assert(saved_thing)
assert_equal(thing.test_to_xml, saved_thing.test_to_xml)
assert_not_same(thing, saved_thing)
pname = "first" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
Xampl.enable_persister(pname, :in_memory)
persister1 = Xampl.persister
#check that the naming and kind checking is working
assert_raise(IncompatiblePersisterRequest){
Xampl.enable_persister(pname, :filesystem)
}
#okay, carry on
Xampl.enable_persister(pname, :in_memory)
persister2 = Xampl.persister
assert_equal(persister1, persister2)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
assert_nil(Xampl.lookup(Thing, "thing"))
assert(nil == thing.persister)
assert(thing.is_changed)
assert(0 == Xampl.count_changed)
Xampl.introduce_to_persister(thing)
assert(thing.persister)
assert_equal(1, Xampl.count_changed)
assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup new stuff")
assert_same(thing, Thing.lookup("thing"), "cannot lookup new stuff")
assert_same(thing, Thing["thing"], "cannot lookup new stuff")
#Xampl.print_stats
assert_equal(1, Xampl.count_changed)
writes = Xampl.sync
assert_equal(1, writes)
assert_equal(0, Xampl.count_changed)
assert(Xampl.lookup(Thing, "thing"))
assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup cached stuff")
Xampl.clear_cache
found = Xampl.lookup(Thing, "thing")
assert_not_equal(thing, found)
assert(thing === found)
#Xampl.print_stats
end
def test_in_memory_persistence_ruby
pname = "test_in_memory_persistence_ruby" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
Xampl.enable_persister(pname, :in_memory, :ruby_format)
persister2 = Xampl.persister
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
Xampl.introduce_to_persister(thing)
Xampl.sync
Xampl.clear_cache
found = Xampl.lookup(Thing, "thing")
assert_not_equal(thing, found)
assert(thing === found)
end
def test_in_memory_persistence_rollback
pname = "first" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
original_persister = Xampl.enable_persister(pname, :in_memory)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
Xampl.introduce_to_persister(thing)
Xampl.rollback
current_persister = Xampl.persister
#assert_not_equal(original_persister, current_persister)
assert_equal(original_persister, current_persister)
# no sync after thing's creation, so thing should NOT exist after rollback
found = Xampl.lookup(Thing, "thing")
assert_nil(found)
assert_equal(original_persister, thing.persister)
#assert_xampl_exception(:live_across_rollback){
# thing.new_stuff
#}
assert_raise(XamplIsInvalid){
thing.new_stuff
}
writes = Xampl.sync
assert_equal(0, writes)
end
def test_in_memory_persistence_rollback_survival
pname = "first" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
original_persister = Xampl.enable_persister(pname, :in_memory)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
Xampl.introduce_to_persister(thing)
Xampl.sync
thing.new_stuff
thing.info = "something"
Xampl.rollback
assert(thing.load_needed)
assert(!thing.is_changed)
assert_nil(thing.info, "attributes not cleared by the rollback")
current_persister = Xampl.persister
#assert_not_equal(original_persister, current_persister)
assert_equal(original_persister, current_persister) # stomp
# a sync done BEFORE the second 'stuff' was added to thing
found = Xampl.lookup(Thing, "thing")
assert_equal(thing, found)
assert_equal(original_persister, current_persister)
assert_equal(original_persister, thing.persister)
assert_equal(current_persister, found.persister)
assert_equal(1, thing.stuff.size)
assert_equal(1, found.stuff.size)
# assert_xampl_exception(:live_across_rollback){
# thing.new_stuff
# }
writes = Xampl.sync
assert_equal(0, writes)
new_thing = found.new_thing("new_thing")
new_thing.new_stuff
writes = Xampl.sync
assert_equal(2, writes)
new_thing.new_stuff
writes = Xampl.sync
assert_equal(1, writes)
end
def test_filesystem_persistence_basics
stuff = Stuff.new
thing = Thing.new
thing << stuff
thing.pid = "thing"
assert_xampl_exception(:name_required){
Xampl.enable_persister(nil, :filesystem)
}
pname = "test_filesystem_persistence_basics_ut" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
Xampl.enable_persister(pname, :filesystem)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
assert_nil(Xampl.lookup(Thing, "thing"))
assert(nil == thing.persister)
assert(thing.is_changed)
assert_equal(0, Xampl.count_changed)
Xampl.introduce_to_persister(thing)
assert(thing.persister)
assert_equal(1, Xampl.count_changed)
assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup new stuff")
#Xampl.print_stats
assert_equal(1, Xampl.count_changed)
writes = Xampl.sync
assert_equal(1, writes)
assert_equal(0, Xampl.count_changed)
assert(Xampl.lookup(Thing, "thing"))
assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup cached stuff")
Xampl.clear_cache
found = Xampl.lookup(Thing, "thing")
assert_not_same(thing, found)
assert(thing === found)
Xampl.clear_cache
# now, changing thing will affect the DB -- VERY SUBTLE POSSIBLIITY OF BUG!
thing.new_stuff
assert_equal(2, thing.stuff.size)
assert_equal(1, found.stuff.size)
writes = Xampl.sync
assert_equal(2, thing.stuff.size)
assert_equal(1, found.stuff.size)
found2 = Xampl.lookup(Thing, "thing")
assert_equal(2, thing.stuff.size)
assert_equal(1, found.stuff.size)
assert_equal(2, found2.stuff.size)
assert(!(found === found2))
assert(thing === found2)
assert_not_equal(found, found2)
#Xampl.print_stats
end
def test_filesystem_persistence_very_many
name = "test_filesystem_persistence_very_many_ut" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
holder = nil
Xampl.transaction(name, :filesystem, automatic=true) do
holder = Thing.new("root")
end
1.upto(200) do |i|
Xampl.transaction(name, :filesystem, automatic=true) do
child = holder.new_thing("child#{i}")
end
end
#Xampl.transaction(name, :filesystem, automatic=true) do
#Xampl.print_stats
#end
Xampl.transaction(name, :filesystem, automatic=true) do
holder.thing.each{ | child |
found = Xampl.lookup(Thing, child.pid)
assert_equal(child, found)
}
#Xampl.print_stats
end
end
def test_filesystem_persistence_over_write_on_parse
name = "test_filesystem_persistence_over_write_on_parse_ut" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
holder = nil
Xampl.transaction(name, :filesystem, automatic=true) do
holder = Thing.new("root")
end
Xampl.transaction(name, :filesystem, automatic=true) do
1.upto(10) do |i|
cname = "child#{i}"
child = holder.new_thing(cname)
child.new_key_value('index').value = cname
end
end
Xampl.transaction(name, :filesystem, automatic=true) do
Xampl.print_stats
end
xml = holder.pp_xml
Xampl.transaction(name, :filesystem, automatic=true) do
1.upto(11) do |i|
cname = "child#{i}"
child = holder.ensure_thing(cname)
child.ensure_key_value('index').value = "changed#{i}"
end
holder.remove_thing("child1")
end
assert_equal(10, holder.thing.size)
assert_equal(holder.children.size, holder.thing.size)
parsed_holder = nil
Xampl.transaction(name, :filesystem, automatic=true) do
parsed_holder = XamplObject.from_xml_string(xml)
end
assert_equal(10, holder.thing.size)
assert_equal(holder.children.size, holder.thing.size)
assert_equal(parsed_holder, holder)
Xampl.transaction(name, :filesystem, automatic=true) do
holder.thing.each{ | child |
found = Xampl.lookup(Thing, child.pid)
assert_equal(child, found)
assert_equal(child, parsed_holder.thing[child.pid])
}
Xampl.print_stats
end
end
def test_filesystem_persistence_ruby
pname = "test_filesystem_persistence_ruby" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
Xampl.enable_persister(pname, :filesystem, :ruby_format)
persister2 = Xampl.persister
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
Xampl.introduce_to_persister(thing)
Xampl.sync
thing.info = "force emptying"
Xampl.rollback
assert(thing.load_needed)
found = Xampl.lookup(Thing, "thing")
assert_equal(thing.object_id, found.object_id)
end
def test_filesystem_persistence_automatic
stuff = Stuff.new
thing = Thing.new
thing << stuff
thing.pid = "thing"
pname = "test_filesystem_persistence_automatic_ut" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
Xampl.enable_persister(pname, :filesystem)
Xampl.auto_persistence
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
assert_equal(thing, Xampl.lookup(Thing, "thing"))
assert(thing.persister)
assert(thing.is_changed)
assert_equal(1, Xampl.count_changed)
assert_equal(thing, Xampl.lookup(Thing, "thing"), "cannot lookup new stuff")
writes = Xampl.sync
assert_equal(1, writes)
assert_equal(0, Xampl.count_changed)
assert(Xampl.lookup(Thing, "thing"))
assert_equal(thing, Xampl.lookup(Thing, "thing"), "cannot lookup cached stuff")
assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup cached stuff")
Xampl.clear_cache
found = Xampl.lookup(Thing, "thing")
assert_not_equal(thing, found)
assert_not_same(thing, found)
root = Thing.new
root.pid = "root"
found2 = root.new_thing("thing")
assert_equal(found, found2, "in automatic persistence mode, supposed to look stuff up")
#Xampl.print_stats
end
def test_filesystem_persistence_rollback
pname = "test_filesystem_persistence_rollback_ut" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
original_persister = Xampl.enable_persister(pname, :filesystem)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
Xampl.introduce_to_persister(thing)
Xampl.rollback
current_persister = Xampl.persister
assert_equal(original_persister, current_persister)
#assert_not_equal(original_persister, current_persister)
# no sync after thing's creation, so thing should NOT exist after rollback
found = Xampl.lookup(Thing, "thing")
assert_nil(found)
assert_equal(original_persister, thing.persister)
#assert_xampl_exception(:live_across_rollback){
# thing.new_stuff
#}
thing.stuff.size
writes = Xampl.sync
assert_equal(0, writes)
end
def test_filesystem_persistence_rollback_survival
pname = "test_filesystem_persistence_rollback_survival_ut" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
original_persister = Xampl.enable_persister(pname, :filesystem)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
Xampl.introduce_to_persister(thing)
assert_equal(1, thing.stuff.size)
Xampl.sync
assert_equal(1, thing.stuff.size)
thing.new_stuff
thing.info = "something"
assert_equal(2, thing.stuff.size)
Xampl.rollback
assert(thing.load_needed)
assert_nil(thing.info, "attributes not cleared by the rollback")
assert(!thing.load_needed)
assert_equal(1, thing.stuff.size)
current_persister = Xampl.persister
assert_equal(original_persister, current_persister)
# a sync done BEFORE the second 'stuff' was added to thing
found = Xampl.lookup(Thing, "thing")
assert_equal(found.object_id, thing.object_id)
assert_equal(original_persister, current_persister)
assert_equal(current_persister, thing.persister)
assert_equal(current_persister, found.persister)
assert(!thing.load_needed)
assert(!thing.is_changed)
thing.stuff.size
assert(!thing.load_needed)
assert(!thing.is_changed)
assert_equal(found.object_id, thing.object_id)
assert_equal(1, thing.stuff.size)
assert_equal(1, found.stuff.size)
#assert_xampl_exception(:live_across_rollback){
# thing.new_stuff
#}
assert(!thing.is_changed)
writes = Xampl.sync
assert_equal(0, writes)
new_thing = found.new_thing("new_thing")
new_thing.new_stuff
writes = Xampl.sync
assert_equal(2, writes)
new_thing.new_stuff
writes = Xampl.sync
assert_equal(1, writes)
Xampl.rollback
assert_equal(0, Xampl.persister.read_count)
thing = Thing.lookup("thing")
assert_not_nil(thing)
assert_equal(0, Xampl.persister.read_count, "not in the cache")
new_thing = thing.thing["new_thing"]
assert_not_nil(new_thing)
assert_equal(0, Xampl.persister.read_count, "not in the cache")
keep_new_thing = new_thing
# these (to xml, ruby) will NOT suck the child thing into memory
xml = thing.test_to_xml
ruby = thing.to_ruby
ruby_thing = XamplObject.from_ruby(ruby)
assert_equal(0, Xampl.persister.read_count, "not in the cache")
# this will trigger the lazy load of new_thing
size = new_thing.stuff.size
assert_equal(0, Xampl.persister.read_count, "not in the cache")
assert_equal(keep_new_thing, new_thing)
assert_equal(new_thing, thing.thing["new_thing"])
Xampl.rollback
# another way to get stuff into memory
# ACTUALLY, this is not legal, there is a cache conflict problem
illegal_lazy_thing = Thing.new
illegal_lazy_thing.pid = "thing"
illegal_lazy_thing.load_needed = true
#assert_xampl_exception(:cache_conflict){
# assert(thing === illegal_lazy_thing)
#}
#assert_raise(XamplIsInvalid){
# # due to a change in xampl this is OK (it isn't invalid yet)
#illegal_lazy_thing.info = "oops"
#}
okay_thing = Thing.lookup("thing")
assert(okay_thing)
okay_thing.info = "okay"
end
def test_escaping
description = Description.new
description.kind = "<>&'\""
description << "<>&'\""
expect = "<>&'\""
assert_equal(expect, description.test_to_xml)
end
def choose_name_test_helper(name, expected_class_name, expected_attribute_name)
original_name = name.dup
class_name, attribute_name = Generator.choose_names(name, "", "")
assert_equal(original_name, name, "changed the original name")
assert_equal(expected_class_name, class_name, "CLASS name wrong")
assert_equal(expected_attribute_name, attribute_name, "ATTRIBUTE name wrong")
end
def test_generator_with_no_namespace
generator = Generator.new
generator.comprehend_from_strings([
%Q{
blah blah blah
}
])
ns = ""
#ns = nil
emap = generator.elements_map
assert_equal(1, emap.size)
elements = emap[ns]
assert_not_nil(elements)
assert_equal(6, elements.element_child.size)
ename = "emph"
element = elements.element_child[ename]
assert_not_nil(element)
assert_equal(ns, element.namespace)
assert_equal("{#{ns}}#{ename}", element.nstag)
assert(!element.empty)
assert(element.has_content)
ename = "description"
element = elements.element_child[ename]
assert_not_nil(element)
assert_equal(ns, element.namespace)
assert_equal("{#{ns}}#{ename}", element.nstag)
assert(!element.empty)
assert(element.has_content)
assert_equal(1, element.attribute_child.size)
assert_not_nil(element.attribute_child["kind"])
assert_nil(element.attribute_child["kind"].namespace)
assert_equal(1, element.child_element_child.size)
cname = "{#{ns}}emph"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("emph", element.child_element_child[cname].element_name)
ename = "stuff"
element = elements.element_child[ename]
assert_not_nil(element)
assert_equal(ns, element.namespace)
assert_equal("{#{ns}}#{ename}", element.nstag)
assert(element.empty)
assert(!element.has_content)
assert_equal(2, element.attribute_child.size)
assert_not_nil(element.attribute_child["kind"])
assert_nil(element.attribute_child["kind"].namespace)
assert_not_nil(element.attribute_child["special"])
assert_equal('http://xampl.com/example/special', element.attribute_child["special"].namespace)
assert_equal(0, element.child_element_child.size)
ename = "keyValue"
element = elements.element_child[ename]
assert_not_nil(element)
assert_equal(ns, element.namespace)
assert_equal("{#{ns}}#{ename}", element.nstag)
assert(element.empty)
assert(!element.has_content)
assert_equal(2, element.attribute_child.size)
assert_not_nil(element.attribute_child["id"])
assert_nil(element.attribute_child["id"].namespace)
assert_not_nil(element.attribute_child["value"])
assert_nil(element.attribute_child["value"].namespace)
assert_equal(0, element.child_element_child.size)
ename = "thing"
element = elements.element_child[ename]
assert_not_nil(element)
assert_equal(ns, element.namespace)
assert_equal("{#{ns}}#{ename}", element.nstag)
assert(element.empty)
assert(!element.has_content)
assert_equal(1, element.attribute_child.size)
assert_equal(1, element.attribute_child.size)
assert_not_nil(element.attribute_child["pid"])
assert_nil(element.attribute_child["pid"].namespace)
assert_equal(5, element.child_element_child.size)
cname = "{#{ns}}description"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("description", element.child_element_child[cname].element_name)
cname = "{#{ns}}keyValue"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("keyValue", element.child_element_child[cname].element_name)
cname = "{#{ns}}stuff"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("stuff", element.child_element_child[cname].element_name)
cname = "{#{ns}}thing"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("thing", element.child_element_child[cname].element_name)
cname = "{#{ns}}things"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("things", element.child_element_child[cname].element_name)
ename = "things"
element = elements.element_child[ename]
assert_not_nil(element)
assert_equal(ns, element.namespace)
assert_equal("{#{ns}}#{ename}", element.nstag)
assert(element.empty)
assert(!element.has_content)
assert_equal(0, element.attribute_child.size)
assert_equal(1, element.child_element_child.size)
cname = "{#{ns}}thing"
assert_not_nil(element.child_element_child[cname])
assert_equal(ns, element.child_element_child[cname].namespace)
assert_equal("thing", element.child_element_child[cname].element_name)
#generator.print_stats
generator.analyse
ename = "emph"
element = elements.element_child[ename]
assert_equal("simple", element.kind, "emph is wrong kind")
assert_nil(element.indexed_by_attr)
assert_nil(element.persisted)
assert_equal("XamplAdHoc", element.package)
assert_equal("Emph", element.class_name)
assert_equal("emph", element.attribute_name)
ename = "description"
element = elements.element_child[ename]
assert_equal("mixed", element.kind, "description is wrong kind")
assert_nil(element.indexed_by_attr)
assert_nil(element.persisted)
assert_equal("XamplAdHoc", element.package)
assert_equal("Description", element.class_name)
assert_equal("description", element.attribute_name)
ename = "stuff"
element = elements.element_child[ename]
assert_equal("empty", element.kind, "stuff is wrong kind")
assert_nil(element.indexed_by_attr)
assert_nil(element.persisted)
assert_equal("XamplAdHoc", element.package)
assert_equal("Stuff", element.class_name)
assert_equal("stuff", element.attribute_name)
ename = "keyValue"
element = elements.element_child[ename]
assert_equal("empty", element.kind, "keyValue is wrong kind")
assert_equal("id", element.indexed_by_attr)
assert_nil(element.persisted)
assert_equal("XamplAdHoc", element.package)
assert_equal("KeyValue", element.class_name)
assert_equal("key_value", element.attribute_name)
ename = "thing"
element = elements.element_child[ename]
assert_equal("data", element.kind, "thing is wrong kind")
assert_equal("pid", element.indexed_by_attr)
assert_not_nil(element.persisted)
assert_equal("XamplAdHoc", element.package)
assert_equal("Thing", element.class_name)
assert_equal("thing", element.attribute_name)
#generator.generate_to_directory(nil)
end
def test_choose_names
choose_name_test_helper("abcd", "Abcd", "abcd")
choose_name_test_helper("Abcd", "Abcd", "abcd")
choose_name_test_helper("abCd", "AbCd", "ab_cd")
choose_name_test_helper("AbCd", "AbCd", "ab_cd")
choose_name_test_helper("ABcd", "ABcd", "abcd")
choose_name_test_helper("ABcdefABCdef", "ABcdefABCdef", "abcdef_abcdef")
choose_name_test_helper("ab-cd", "AbCd", "ab_cd")
choose_name_test_helper("Ab-Cd", "AbCd", "ab_cd")
choose_name_test_helper("ab--cd", "AbCd", "ab_cd")
choose_name_test_helper("Ab--Cd", "AbCd", "ab_cd")
choose_name_test_helper("ab_-cd", "AbCd", "ab_cd")
choose_name_test_helper("Ab_-Cd", "AbCd", "ab_cd")
choose_name_test_helper("ab__cd", "AbCd", "ab_cd")
choose_name_test_helper("Ab__Cd", "AbCd", "ab_cd")
choose_name_test_helper("ab:cd", "AbCd", "ab_cd")
choose_name_test_helper("Ab:Cd", "AbCd", "ab_cd")
choose_name_test_helper("ab.cd", "AbCd", "ab_cd")
choose_name_test_helper("ab9cd", "AbCd", "ab_cd")
choose_name_test_helper("ab9Cd", "AbCd", "ab_cd")
end
# TODO -- test no namespace
def test_bug_indexed_child_same_pid_added_twice
element = Element.new
attr0 = element.new_attribute("repeated")
assert_equal(1, element.attribute_child.size)
assert_equal(1, element.attribute_child.size)
assert_equal(1, element.children.size)
assert_equal(attr0, element.children[0])
ce1 = element.new_child_element("something")
assert_equal(1, element.attribute_child.size)
assert_equal(1, element.attribute_child.size)
assert_equal(2, element.children.size)
assert_equal(attr0, element.children[0])
assert_equal(ce1, element.children[1])
attr2 = element.new_attribute("repeated")
assert_equal(1, element.attribute_child.size)
assert_equal(1, element.attribute_child.size)
assert_equal(2, element.children.size)
assert_equal(ce1, element.children[0])
assert_equal(attr2, element.children[1])
end
def test_cycles_and_bushy_lookup
pname = "test_cycles_and_bushy" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
#Xampl.enable_persister(pname, :filesystem)
Xampl.enable_persister(pname, :in_memory)
Xampl.auto_persistence
root = Thing.new("root")
root.info = "one"
root.new_thing("branch1").new_thing("leaf").info = "two"
root.new_thing("branch2").new_thing("leaf").info = "three"
root.new_thing("branch3").new_thing("leaf").info = "four"
root.new_thing("cycle0").info = "five"
Thing.lookup("cycle0").new_thing("cycle1").new_thing("cycle2").info = "six"
Thing.lookup("cycle2").new_thing("cycle0")
assert(Thing.lookup("cycle2").thing["cycle0"] == Thing.lookup("cycle0"))
assert(Thing.lookup("root").thing["cycle0"] == Thing.lookup("cycle0"))
Xampl.sync
assert_equal(8, CountingVisitor.new.start(root).count)
pp_xml = root.pp_xml
#puts root.pp_xml
end
def test_cycles_and_bushy2_locals
pname = "test_cycles_and_bushy" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
#Xampl.enable_persister(pname, :filesystem)
Xampl.enable_persister(pname, :in_memory)
Xampl.auto_persistence
root = Thing.new("root")
root.new_thing("branch1").new_thing("leaf")
root.new_thing("branch2").new_thing("leaf")
root.new_thing("branch3").new_thing("leaf")
cycle0 = root.new_thing("cycle0")
cycle0.new_thing("cycle1").new_thing("cycle2").new_thing("cycle0")
assert_equal(Thing.lookup("cycle2").thing["cycle0"],
Thing.lookup("root").thing["cycle0"])
Xampl.sync
assert_equal(8, CountingVisitor.new.start(root).count)
#puts root.pp_xml
end
def test_internal_cycles_and_bushy
pname = "test_internal_cycles_and_bushy" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
#Xampl.enable_persister(pname, :filesystem)
Xampl.enable_persister(pname, :in_memory)
Xampl.auto_persistence
root = Thing.new("root")
root.info = "root"
(branch1 = Branch.new).info='one'
(branch2 = Branch.new).info='two'
(branch3 = Branch.new).info='three'
(branch4 = Branch.new).info='four'
(branch5 = Branch.new).info='five'
#puts branch1.pp_xml
#
# 1
# 2 3
# 4
# 1
# and 5 is a child of 1, 2, 3, and 4
root << branch1
branch1 << branch2
branch1 << branch3
branch2 << branch4
branch3 << branch4
branch4 << branch1
branch1 << branch5
branch2 << branch5
branch3 << branch5
branch4 << branch5
#assert_xampl_exception(:cycle_detected_in_xampl_cluster){
assert_xampl_exception(:cycle_detected_in_xampl_cluster){
xml = PersistXML.new("").start(root).done
}
assert_xampl_exception(:cycle_detected_in_xampl_cluster){
Xampl.sync
}
#there is one thing and 5 branches, so 6 different things
assert_equal(6, CountingVisitor.new.start(root).count)
pp_xml = root.pp_xml
end
# def test_fsdb_extension_persistence_basics
# require 'persister/fsdb'
# stuff = Stuff.new
# thing = Thing.new
# thing << stuff
#
# thing.pid = "thing"
#
# assert_xampl_exception(:name_required){
# Xampl.enable_persister(nil, :fsdb)
# }
#
# pname = "test_fsdb_extension_persistence_basics" << Time.now.strftime("%Y%m%d-%H%M-%S") << rand.to_s
# Xampl.enable_persister(pname, :fsdb)
#
# stuff = Stuff.new
# thing = Thing.new
# thing.pid = "thing"
# thing << stuff
#
# assert_nil(Xampl.lookup(Thing, "thing"))
#
# assert(nil == thing.persister)
# assert(thing.is_changed)
# assert_equal(0, Xampl.count_changed)
#
# Xampl.introduce_to_persister(thing)
#
# assert(thing.persister)
# assert_equal(1, Xampl.count_changed)
# assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup new stuff")
#
# #Xampl.print_stats
#
# assert_equal(1, Xampl.count_changed)
# writes = Xampl.sync
# assert_equal(1, writes)
# assert_equal(0, Xampl.count_changed)
# assert(Xampl.lookup(Thing, "thing"))
#
# thing2 = Xampl.lookup(Thing, "thing")
# assert_same(thing, thing2, "cannot lookup cached stuff")
#
# Xampl.clear_cache
#
# found = Xampl.lookup(Thing, "thing")
# assert_not_same(thing, found)
# assert(thing === found)
#
# Xampl.clear_cache
#
# # now, changing thing will affect the DB -- VERY SUBTLE POSSIBLIITY OF BUG!
# thing.new_stuff
# assert_equal(2, thing.stuff.size)
# assert_equal(1, found.stuff.size)
#
# writes = Xampl.sync
#
# assert_equal(2, thing.stuff.size)
# assert_equal(1, found.stuff.size)
#
# found2 = Xampl.lookup(Thing, "thing")
#
# assert_equal(2, thing.stuff.size)
# assert_equal(1, found.stuff.size)
# assert_equal(2, found2.stuff.size)
#
# assert(!(found === found2))
# assert(thing === found2)
#
# assert_not_equal(found, found2)
#
# #Xampl.print_stats
# end
def test_simple_extension_persistence_basics
stuff = Stuff.new
thing = Thing.new
thing << stuff
thing.pid = "thing"
Xampl.enable_persister(nil, :simple)
stuff = Stuff.new
thing = Thing.new
thing.pid = "thing"
thing << stuff
assert_nil(Xampl.lookup(Thing, "thing"))
assert(nil == thing.persister)
assert(thing.is_changed)
assert_equal(0, Xampl.count_changed)
Xampl.introduce_to_persister(thing)
assert(thing.persister)
assert_equal(0, Xampl.count_changed)
assert_same(thing, Xampl.lookup(Thing, "thing"), "cannot lookup new stuff")
#Xampl.print_stats
assert_equal(0, Xampl.count_changed)
writes = Xampl.sync
assert_equal(0, Xampl.count_changed)
assert(Xampl.lookup(Thing, "thing"))
thing2 = Xampl.lookup(Thing, "thing")
assert_same(thing, thing2, "cannot lookup cached stuff")
found = Xampl.lookup(Thing, "thing")
assert_equal(thing.object_id, found.object_id)
#Xampl.print_stats
end
def check_parents(xampl, parent=nil)
if (nil != parent) then
found = false
xampl.parents.each{ | p |
found = true if (parent == p)
}
assert(found)
else
if (xampl.kind_of? XamplObject)
assert((nil == xampl.parents) || (0 == xampl.parents.size))
end
end
xampl.children.each{ | child |
check_parents(child, xampl) if (child.kind_of? XamplObject)
}
end
end