#!/usr/bin/env python from __future__ import with_statement import sys, os sys.path = ([os.path.dirname(os.path.dirname(os.path.realpath(__file__)))] + sys.path) __requires__='Bazki' import pkg_resources pkg_resources.require('Bazki') import unittest, warnings import re import unicodedata from bazbase import custom, db, flavors, wiki, testing, structure from bazbase.conversion import invalidate_cache, to_python, render, render_propval #custom.get_sqlalchemy_args = lambda: {'url': 'sqlite://'} testing.set_up_for_tests() if '-v' in sys.argv: def debug(*s): print >>sys.stderr,' '.join(s) else: def debug(*s): pass from redbeans.creole import tokenize g_query_count = 0 from sqlalchemy import event from sqlalchemy.engine import Engine @event.listens_for(Engine, "after_cursor_execute") def after_cursor_execute(conn, cursor, statement, parameters, context, executemany): global g_query_count g_query_count += 1 class TestHelpers(unittest.TestCase): def test_safesplit_tags(self): self.assertEqual([([Text(u'Foo')], None), ([Text(u'Bar')], (u'else', None))], wiki.safesplit_tags(tokenize('Foo<>Bar'), ('else',))) self.assertEqual([([Text(u'FooBar')], None)], wiki.safesplit_tags(tokenize('FooBar'), ('else',))) self.assertEqual([([Start(MACRO, (u'if', None)), Text(u'Foo'), Entity(MACRO, (u'else', None)), Text(u'Bar'), End(MACRO, u'if')], None)], wiki.safesplit_tags( tokenize('<>Foo<>Bar<>'), ('else',))) class TestBazbase(unittest.TestCase): def setUp(self): custom.APP_NAME = 'BazbaseTest' invalidate_cache() debug("=== Setup B ===") db.begin_transaction() try: structure.clear_database() disp = structure.create_prop(u'disposition', u'string') disp.set_default('') structure.create_prop(u'listed', u'boolean') root = structure.create_root_element(u'Root') root.set_prop(u'comment', 'cheese') root.set_prop(u'disposition', 'sunny') root.set_prop(u'listed', 'false') structure.get_element(u'Root') debug("Child...") child = root.create_child(u'Child') debug("Bees...") child.set_prop(u'comment', 'bees') page = root.create_child(u'Page') page.set_prop(u'comment', '[[http://sevenmonkey.mit.edu/Japan/Early Netsuke]]') page.set_prop(u'product', '[[Early Netsuke]] were pretty \emph{awesome}...') page.set_prop(u'product2', '[[EarlyNetsuke]] were pretty \emph{awesome}...') debug("Flushing...") structure.flush_database_for_test() except: db.abort_transaction() raise def tearDown(self): db.abort_transaction() wiki.clear_eval_state() def testBasics(self): root = structure.get_element(u'Root') self.assertEqual(render(root, u'disposition'), u'sunny') self.assertEqual( render(structure.get_element_with({u'disposition': u'sunny'}), u'comment'), u'cheese') self.assertEqual(render(root, u'listed'), u'False') self.assertFalse(to_python(root, u'listed')) def testTeX(self): root = structure.get_element(u'Root') root.set_prop(u'disposition', "PB&J") self.assertEqual(r'PB\&J', render(root, u'disposition', u'tex')) root.set_prop(u'disposition', 'Examples & Such') root.set_prop(u'comment', '[[http://example.com|<>]]') self.assertEqual(render(root, u'comment', u'tex'), u'\\href{http://example.com}{Examples \\& Such}') def testHTML(self): self.assertEqual(render_propval(u'Page', u'comment', u'html'), u'

http://sevenmonkey.mit.edu/Japan/Early Netsuke

') self.assertEqual(render_propval(u'Page', u'product', u'html'), u'

Early Netsuke were pretty awesome\u2026

') self.assertEqual(render_propval(u'Page', u'product2', u'html'), u'

EarlyNetsuke were pretty awesome\u2026

') def testReference(self): structure.create_prop(u'mother',u'reference') root = structure.get_element(u'Root') root.set_prop(u'mother', '') child = structure.get_element(u'Child') child.set_prop(u'mother', '[[%s]]' % root.ename.encode('utf-8')) self.assertEqual(flavors.Reference(root, [], child), to_python(child, u'mother')) kids = structure.search_elements({u'mother': structure.get_element(u'Root')}) self.assertEqual([child], kids) self.assertEqual(None, to_python(root, u'mother')) self.assertEqual('', render(root, u'mother')) root.set_prop(u'comment', '<>') self.assertEqual('sunny', render(root, u'comment')) def testReferences(self): structure.create_prop(u'fish', u'references') page = structure.get_element(u'Page') page.set_prop(u'name', 'Page') root = structure.get_element(u'Root') root.set_prop(u'fish', '[[Page]]') self.assertEqual([flavors.Reference(page, [], root)], to_python(root, u'fish')) root.set_prop(u'comment', '<><><>') self.assertEqual(u'Page', render(root, u'comment')) root.set_prop(u'fish', '[[Page]], [[Nonexistent]]') wiki.init_eval_state(None, None, 'txt', None) self.assertRaises(wiki.WikiException, wiki.baz_eval, 'Root.fish') def testArgReferences(self): structure.create_prop(u'fish', u'references') page = structure.get_element(u'Page') page.set_prop(u'name', 'Page: <<1/>>') root = structure.get_element(u'Root') root.set_prop(u'fish', '[[Page/Tree]]') self.assertEqual([flavors.Reference(page, [u'Tree'], root)], to_python(root, u'fish')) root.set_prop(u'comment', '<><><>') self.assertEqual(u'Page: Tree', render(root, u'comment')) def testMultiArgReferences(self): structure.create_prop(u'fish', u'references') structure.create_prop(u'thing', u'string') structure.create_prop(u'other', u'string') page = structure.get_element(u'Page') page.set_prop(u'name', r'Page: \1, not \2 (\thing, \other, \disposition)') page.set_prop(u'disposition', 'Dispo') page.set_prop(u'thing', 'Thing') child = structure.get_element(u'Child') child.set_prop(u'fish', '[[Page/Tree/Grass]]') child.set_prop(u'other', 'Other') root = structure.get_element(u'Root') third = root.create_child(u'Third') third.set_prop(u'disposition', 'Royal') third.set_prop(u'thing', 'Crown') third.set_prop(u'other', 'Wish') self.assertEqual([flavors.Reference(page, [u'Tree', u'Grass'], child)], to_python(child, u'fish')) child.set_prop(u'comment', '<><><>') self.assertEqual(u'Page: Tree, not Grass (Thing, Other, Dispo)', render(child, u'comment')) child.set_prop(u'comment', '<><><><><>') self.assertEqual(u'Page: Tree, not Grass (Thing, Other, Dispo)', render(child, u'comment')) def testMetadata(self): child = structure.get_element(u'Child') self.assertEqual({u'comment': u'bees', u'listed': u'false', u'disposition': u''}, child.get_nice_value_map()) def testMetadataQueries(self): keys = ['get_value_map'] child = structure.get_element(u'Child') for k in keys: was = g_query_count getattr(child, k)() self.assertEqual(1, g_query_count - was) class TestTransactions(unittest.TestCase): def setUp(self): debug("=== Setup T ===") db.begin_transaction() try: structure.clear_database() disp = structure.create_prop(u'disposition', u'string') disp.set_default('') root = structure.create_root_element(u'Root') root.set_prop(u'comment', 'cheese') root.set_prop(u'disposition', 'sunny') child = root.create_child(u'Child') child.set_prop(u'comment', 'bees') except: db.abort_transaction() raise else: db.commit_transaction() def testBasics(self): db.begin_transaction() try: root = structure.get_element(u'Root') root.set_prop(u'comment', 'fleas') self.assertEqual(render_propval(u'Root', u'comment'), u'fleas') finally: db.abort_transaction() db.begin_transaction() try: self.assertEqual(render_propval(u'Root', u'comment'), u'cheese') finally: db.abort_transaction() def testSearchability(self): db.begin_transaction() try: self.assertEqual( render(structure.get_element_with({u'disposition': u'sunny'}), u'comment'), u'cheese') finally: db.abort_transaction() db.begin_transaction() try: root = structure.get_element(u'Root') root.set_prop(u'comment', 'fleas') self.assertEqual( render(structure.get_element_with({u'disposition': u'sunny'}), u'comment'), u'fleas') finally: db.abort_transaction() db.begin_transaction() try: self.assertEqual( render(structure.get_element_with({u'disposition': u'sunny'}), u'comment'), u'cheese') finally: db.abort_transaction() def testChildren(self): structure.verify_tree_for_test() with db.begin_transaction(): e = structure.get_element(u'Child').create_child(u'Fish') e.set_prop(u'comment', '42') structure.verify_tree_for_test() db.begin_transaction() try: e = structure.get_element(u'Child').create_child(u'Dish') e.set_prop(u'comment', '47') self.assertEqual(e.get_parent(), structure.get_element(u'Child')) finally: db.abort_transaction() structure.verify_tree_for_test() with db.begin_transaction(): fish = structure.get_element(u'Fish') e = fish.create_child(u'Sish') e.set_prop(u'comment', '11') f = fish.create_child(u'Cish') f.set_prop(u'comment', '12') g = e.create_child(u'Eish') g.set_prop(u'comment', '13') self.assertEqual(fish.get_parent(), structure.get_element(u'Child')) self.assertEqual(e.get_parent(), fish) self.assertEqual(f.get_parent(), fish) self.assertEqual(g.get_parent(), e) structure.verify_tree_for_test() with db.begin_transaction(): c= structure.get_element(u'Child') d= structure.get_element(u'Fish') e= structure.get_element(u'Sish') f= structure.get_element(u'Cish') g= structure.get_element(u'Eish') f.set_parent(c) self.assertEqual(d.get_parent(),c) self.assertEqual(e.get_parent(),d) self.assertEqual(f.get_parent(),c) self.assertEqual(g.get_parent(),e) structure.verify_tree_for_test() with db.begin_transaction(): c= structure.get_element(u'Child') d= structure.get_element(u'Fish') e= structure.get_element(u'Sish') f= structure.get_element(u'Cish') g= structure.get_element(u'Eish') e.set_parent(c) f.set_parent(d) self.assertEqual(d.get_parent(),c) self.assertEqual(e.get_parent(),c) self.assertEqual(f.get_parent(),d) self.assertEqual(g.get_parent(),e) structure.verify_tree_for_test() with db.begin_transaction(): # Emulate exactly what bazki.edit does e = structure.get_element(u'Wombat') if e is None: e = structure.get_element(u'Child').create_child(u'Wombat') else: self.fail("There shouldn't already be a Wombat.") e.set_prop(u'comment', 'waah') structure.verify_tree_for_test() with db.begin_transaction(): e = structure.get_element(u'Dombat') if e is None: e = structure.get_element(u'Child').create_child(u'Dombat') else: self.fail("There shouldn't already be a Dombat.") e.set_prop(u'comment', 'daah') structure.verify_tree_for_test() from redbeans.parser import Parser from redbeans.formats import Format from redbeans.tokens import * class TestWiki(unittest.TestCase): def test_parse_macro_args(self): self.assertEqual(wiki.parse_macro_args(['4']), {1:'4'}) self.assertEqual(wiki.parse_macro_args(['4','17']), {1:'4',2:'17'}) self.assertEqual(wiki.parse_macro_args(['4', '"17"']), {1:'4',2:'"17"'}) self.assertEqual(wiki.parse_macro_args(['4', 'foo="17"']), {1:'4','foo':'"17"'}) self.assertEqual(wiki.parse_macro_args(['4', '(foo=="17")']), {1:'4',2:'(foo=="17")'}) self.assertEqual(wiki.parse_macro_args(['4', '(foo!="17")']), {1:'4',2:'(foo!="17")'}) self.assertEqual(wiki.parse_macro_args(['4', 'foo=="17"']), {1:'4',2:'foo=="17"'}) self.assertEqual(wiki.parse_macro_args(['4', 'foo!="17"']), {1:'4',2:'foo!="17"'}) self.assertEqual(wiki.parse_macro_args( ["recursive_get(leaf, 'stuff')"]), {1: "recursive_get(leaf, 'stuff')"}) def test_baz_eval(self): with db.begin_transaction(): wiki.init_eval_state(None, None, 'txt', None) self.assertEqual(wiki.baz_eval("3+5"), 8) self.assertEqual(wiki.baz_eval("'3+5'"), "3+5") self.assertEqual(wiki.baz_eval(""), "") self.assertRaises(wiki.WikiException, wiki.baz_eval, "'3'.__class__") class TestWikiWithDB(unittest.TestCase): def setUp(self): debug("=== Setup B ===") db.begin_transaction() try: structure.clear_database() disp = structure.create_prop(u'disposition', u'string') disp.set_default('') answ = structure.create_prop(u'answer', u'integer') answ.set_default('42') root = structure.create_root_element(u'Root') root.set_prop(u'comment', 'cheese') root.set_prop(u'disposition', 'sunny') root.set_prop(u'answer', '17') structure.get_element(u'Root') debug("Child...") child = root.create_child(u'Child') debug("Bees...") child.set_prop(u'comment', 'bees') page = root.create_child(u'Page') page.set_prop(u'comment', '[[http://sevenmonkey.mit.edu/Japan/Early Netsuke]]') page.set_prop(u'product', '[[Early Netsuke]]') debug("Flushing...") structure.flush_database_for_test() wiki.clear_eval_state() wiki.init_eval_state(root, None, 'txt', 'text') except: db.abort_transaction() raise def tearDown(self): db.abort_transaction() wiki.clear_eval_state() def test_baz_eval(self): parser = Parser(Format, wiki.macro_func) self.assertEquals(wiki.baz_eval(u"Root.disposition"), "sunny") self.assertEquals(wiki.baz_eval(u"Root.answer"), 17) self.assertEquals(wiki.baz_eval(u"Root.answer+Root.answer"), 34) self.assertEquals(wiki.baz_eval(u"'test'"), "test") def test_full_eval(self): parser = Parser(Format, wiki.macro_func) self.assertEquals(list(wiki.full_eval(u"Root.disposition")), [Text(u"sunny")]) self.assertEquals(list(wiki.full_eval(u"Root.answer")), [Text(u"17")]) self.assertEquals(list(wiki.full_eval(u"Root.answer+Root.answer")), [Text(u"17"), Text(u"17")]) self.assertEquals(list(wiki.full_eval(u"Root.comment")), [Text(u"cheese")]) self.assertEquals(list(wiki.full_eval(u"'test'")), [Text(u"test")]) class TestMacros(unittest.TestCase): def setUp(self): debug("=== Setup B ===") db.begin_transaction() try: structure.clear_database() disp = structure.create_prop(u'disposition', u'string') disp.set_default('') answ = structure.create_prop(u'answer', u'integer') answ.set_default('42') root = structure.create_root_element(u'Root') root.set_prop(u'comment', 'cheese') root.set_prop(u'disposition', 'sunny') root.set_prop(u'answer', '17') structure.flush_database_for_test() except: db.abort_transaction() raise def tearDown(self): db.abort_transaction() def test_if(self): root = structure.get_element(u'Root') root.set_prop(u'comment', '<>42<>') self.assertEqual('42', render(root, u'comment')) root.set_prop(u'comment', '<>37<>') self.assertEqual('37', render(root, u'comment')) root.set_prop(u'comment', '<>2<>8<>4<>') self.assertEqual('284', render(root, u'comment')) root.set_prop(u'comment', '<>0<>9<>6<><>4<>') self.assertEqual('06', render(root, u'comment')) root.set_prop(u'comment', '''<> <> 9 <> +6 <> <> 4 <>''') self.assertEqual('+6', render(root, u'comment').strip()) def test_link(self): root = structure.get_element(u'Root') root.set_prop(u'comment', '<>Packet as PDF<>') root.set_prop(u'username', 'fish') self.assertEqual( '

Packet as PDF

', render(root, u'comment', u'html')) def test_local_link(self): root = structure.get_element(u'Root') root.set_prop(u'comment', '<>Root<>') self.assertEqual( '

Root

', render(root, u'comment', u'html')) def test_foreach(self): root = structure.get_element(u'Root') t = root.create_child(u'Tree') a = t.create_child(u'Aspen') a.set_prop(u'disposition', 'arid') a.set_prop(u'answer', '42') b = t.create_child(u'Birch') b.set_prop(u'disposition', 'balmy') b.set_prop(u'answer', '7') c = t.create_child(u'Cedar') c.set_prop(u'disposition', 'cloudy') c.set_prop(u'answer', '17') root.set_prop(u'comment', '''<> * <><>''') self.assertEqual(''' * arid * balmy * cloudy''', render(root, u'comment')) root.set_prop(u'comment', '''<> * <><>''') self.assertEqual(''' * balmy * cloudy * arid''', render(root, u'comment')) root.set_prop(u'comment', '''<> * <><>''') self.assertEqual(''' * arid * balmy''', render(root, u'comment')) root.set_prop(u'comment', '''<> * <><>''') self.assertEqual(''' * arid * balmy * cloudy''', render(root, u'comment')) root.set_prop(u'comment', '''<> * <><>''') self.assertEqual(''' * None.''', render(root, u'comment')) trees = structure.create_prop(u'trees', u'labeledrefs') trees.set_default('') root.set_prop(u'trees', '[[Birch|your favorite]], [[Aspen|nice too]]') root.set_prop(u'comment', '''<> * **<>**: <><>''') self.assertEqual(''' * *Birch*: your favorite * *Aspen*: nice too''', render(root, u'comment')) root.set_prop(u'comment', '''<> * <><> <> * <><>''') root.set_prop(u'dream', '''<>''') self.assertEqual(''' * arid * balmy * cloudy * Aspen * Birch * Cedar''', render(root, u'comment')) self.assertEqual('''
  • arid
  • balmy
  • cloudy
  • Aspen
  • Birch
  • Cedar
''', render(root, u'comment', 'html')) self.assertEqual('''
  • arid
  • balmy
  • cloudy
  • Aspen
  • Birch
  • Cedar
''', render(root, u'dream', 'html')) root.set_prop(u'comment', '''== Trees == <> * <><>''') self.assertEqual('''

Trees

  • arid
  • balmy
  • cloudy
''', render(root, u'comment', 'html')) self.assertEqual('''

Trees

  • arid
  • balmy
  • cloudy
''', render(root, u'dream', 'html')) def test_recursive_get(self): root = structure.get_element(u'Root') stuff = structure.create_prop(u'stuff', u'references') stuff.set_default('') root.set_prop(u'stuff', '[[Aspen]]') t = root.create_child(u'Tree') a = t.create_child(u'Aspen') a.set_prop(u'stuff', '[[Cedar]]') b = t.create_child(u'Birch') c = t.create_child(u'Cedar') root.set_prop(u'comment', '''<> * <><>''') self.assertEqual(''' * Aspen * Cedar''', render(root, u'comment')) def test_foreachpropin(self): root = structure.get_element(u'Root') structure.create_prop(u'fish', u'raw') structure.create_prop(u'dish', u'raw') structure.create_prop(u'wish', u'raw') root.set_prop(u'fish', 'carp') root.set_prop(u'dish', 'bowl') root.set_prop(u'wish', 'star') root.set_prop(u'comment', '''<> * **<>**: <><>''') self.assertEqual(''' * *fish*: carp * *dish*: bowl * *wish*: star''', render(root, u'comment')) def test_eval(self): root = structure.get_element(u'Root') root.set_prop(u'comment', '''<>''') self.assertEqual('''True''', render(root, u'comment')) def test_accents(self): root = structure.get_element(u'Root') root.set_prop(u'comment', r'''Pok\'emon ma\~nana look\`ed at Zo\"e in T\=oky\=o.''') self.assertEqual(u'''Pok\u00e9mon ma\u00f1ana look\u00e8d at Zo\u00eb in T\u014dky\u014d.''', unicodedata.normalize('NFC', render(root, u'comment'))) def test_implicit(self): root = structure.get_element(u'Root') root.set_prop(u'substitution', r'''\disposition: \answer''') self.assertEqual('''sunny: 17''', render(root, u'substitution')) page = root.create_child(u'Page') page.set_prop(u'comment', r'''I said, "\Root".''') page.set_prop(u'disposition', 'sad') self.assertEqual(u'I said, \u201Csunny: 17\u201D.', render(page, u'comment')) structure.create_prop(u'end', u'string') page.set_prop(u'end', '!') root.set_prop(u'substitution', r'''\disposition: \answer\end''') self.assertEqual(u'I said, \u201Csunny: 17!\u201D.', render(page, u'comment')) class TestCaching(unittest.TestCase): def setUp(self): invalidate_cache() debug("=== Setup C ===") TestCaching.index = 0 # Put nondeterministic macros that do and don't add DISCORDIA def arbitrary(arglist): TestCaching.index += 1 yield Text(unicode(TestCaching.index)) wiki.macros.arbitrary = arbitrary def discord(arglist): wiki.eval_state.dependencies.makeUncacheable() TestCaching.index += 1 yield Text(unicode(TestCaching.index)) wiki.macros.discord = discord with db.begin_transaction(): structure.clear_database() structure.create_prop(u'disposition', u'string') root = structure.create_root_element(u'Root') root.set_prop(u'comment', '<>') root.set_prop(u'disposition', '<>') root.set_prop(u'mood', '<>') root.set_prop(u'attitude', '<>') structure.flush_database_for_test() def test_txt(self): with db.begin_transaction(): e = structure.get_element(u'Root') # This is uncachable. self.assertNotEqual(render(e, u'comment'), render(e, u'comment')) # Caching should ensure that these are the same. disposition = render(e, u'disposition') self.assertEqual(disposition, render(e, u'disposition')) self.assertEqual(render(e, u'mood'), render(e, u'mood')) # These should be diffferent, because references skip caching. self.assertNotEqual(render(e, u'disposition'), render(e, u'mood')) # These should be the same because of explicit caching. self.assertEqual(render(e, u'disposition'), render(e, u'attitude')) # Should be consistent with the same thing in a separate transaction. with db.begin_transaction(): e = structure.get_element(u'Root') self.assertEqual(disposition, render(e, u'disposition')) class TestRenderer(unittest.TestCase): def setUp(self): with db.begin_transaction(): structure.clear_database() root = structure.create_root_element(u'Root') root.set_prop(u'comment', 'wombat') root.set_prop(u'name', 'Root') def test_render(self): from bazbase import renderer renderer.start_render(u'Root', [u'comment'], u'html') self.assertEqual({u'comment': u'

wombat

'}, renderer.wait_for_render(u'Root', [u'comment'], u'html')) def test_two(self): from bazbase import renderer renderer.start_render(u'Root', [u'comment', u'name'], u'html') m = renderer.wait_for_render(u'Root', [u'comment', u'name'], u'html') self.assertTrue(u'comment' in m or u'name' in m, repr(m)) if __name__ == "__main__": warnings.simplefilter("error") warnings.filterwarnings('ignore', "cgi.parse_qsl is deprecated") unittest.main()