def test_adding_fields_to_type(self): schema = Schema("schema") @schema.define class Test: i = int db = self.createNewDb() db.subscribeToSchema(schema) with db.transaction(): t = Test(i=1) schema2 = Schema("schema") @schema2.define class Test: i = int k = int db2 = self.createNewDb() db2.subscribeToSchema(schema2) t = Test.fromIdentity(t._identity) with db2.view(): self.assertEqual(t.i, 1) self.assertEqual(t.k, 0)
def test_database_object(self): s = Schema("testschema") @s.define class T: val = int @property def aProperty(self): return self._identity + 1 @staticmethod def aStaticMethod(x): return x + 1 def aMethod(self, x): return self._identity + x self.assertEqual(T.fromIdentity(123)._identity, 123) self.assertEqual(T.fromIdentity(123).aProperty, 124) self.assertEqual(T.fromIdentity(123).aStaticMethod(10), 11) self.assertEqual(T.fromIdentity(123).aMethod(10), 133) with self.assertRaisesRegex(Exception, "without an active"): T.fromIdentity(123).val
def test_indices_update_during_transactions(self): db = self.createNewDb() schema = Schema("test_schema") @schema.define class Object: k = Indexed(int) db.subscribeToSchema(schema) with db.transaction() as v: self.assertEqual(Object.lookupAll(k=10), ()) o1 = Object(k=10) self.assertEqual(Object.lookupAll(k=10), (o1, )) o1.k = 20 self.assertEqual(Object.lookupAll(k=10), ()) self.assertEqual(Object.lookupAll(k=20), (o1, )) o1.delete() self.assertEqual(Object.lookupAll(k=10), ()) self.assertEqual(Object.lookupAll(k=20), ())
def test_index_functions(self): db = self.createNewDb() schema = Schema("test_schema") @schema.define class Object: k = Indexed(int) pair_index = Index('k', 'k') db.subscribeToSchema(schema) with db.transaction(): o1 = Object(k=10) with db.view() as v: self.assertEqual(Object.lookupAll(k=10), (o1, )) self.assertEqual(Object.lookupAll(k=20), ()) self.assertEqual(Object.lookupAll(pair_index=(10, 10)), (o1, )) self.assertEqual(Object.lookupAll(pair_index=(10, 11)), ()) with self.assertRaises(Exception): self.assertEqual(Object.lookupAll(pair_index=(10, "hi")), (o1, ))
def test_index_consistency(self): db = self.createNewDb() schema = Schema("test_schema") @schema.define class Object: x = int y = int pair = Index('x', 'y') db.subscribeToSchema(schema) with db.transaction(): o = Object(x=0, y=0) t1 = db.transaction() t2 = db.transaction() with t1.nocommit(): o.x = 1 with t2.nocommit(): o.y = 1 t1.commit() with self.assertRaises(RevisionConflictException): t2.commit() with self.assertRaises(Exception): with db.transaction().consistency(writes=True): o.y = 2
def test_index_transaction_conflicts(self): db = self.createNewDb() schema = Schema("test_schema") @schema.define class Object: k = Indexed(int) db.subscribeToSchema(schema) with db.transaction(): o1 = Object(k=10) o2 = Object(k=20) o3 = Object(k=30) t1 = db.transaction().consistency(full=True) t2 = db.transaction().consistency(full=True) with t1.nocommit(): o2.k = len(Object.lookupAll(k=10)) with t2.nocommit(): o1.k = 20 t2.commit() with self.assertRaises(RevisionConflictException): t1.commit()
def test_serialization_contexts(self): db = self.createNewDb() class ArbitraryBaseClass: def __init__(self, x): self.x = x class ArbitrarySubclass(ArbitraryBaseClass): def __init__(self, x, y): super().__init__(x) self.y = y db.setSerializationContext( SerializationContext({ 'ABC': ArbitraryBaseClass, 'SUB': ArbitrarySubclass })) schema = Schema("test_schema") @schema.define class HoldsArbitrary: holding = ArbitraryBaseClass @schema.define class HoldsObject: holding = object db.subscribeToSchema(schema) with db.transaction(): x = HoldsArbitrary(holding=ArbitraryBaseClass(10)) self.assertEqual(x.holding.x, 10) with db.transaction(): self.assertEqual(x.holding.x, 10) self.assertIsInstance(x.holding, ArbitraryBaseClass) x.holding = ArbitrarySubclass(10, 20) with db.transaction(): self.assertEqual(x.holding.x, 10) self.assertEqual(x.holding.y, 20) self.assertIsInstance(x.holding, ArbitrarySubclass) with self.assertRaises(Exception): with db.transaction(): x.holding = "hi" with db.transaction(): x = HoldsObject(holding="hi") x.holding = 10 with db.transaction(): self.assertEqual(x.holding, 10)
def test_frozen_schema(self): schema = Schema("test_schema") @schema.define class Object: x = int y = int Object.fromIdentity("hi") with self.assertRaises(AttributeError): schema.SomeOtherObject
def test_default_constructor_for_list(self): db = self.createNewDb() schema = Schema("test_schema") @schema.define class Object: x = TupleOf(int) db.subscribeToSchema(schema) with db.transaction(): n = Object() self.assertEqual(len(n.x), 0)
def test_subscription_matching_is_linear(self): schemas = [] dbs = [] db = self.createNewDb() while len(schemas) < 20: #make a new schema s = Schema("schema_" + str(len(schemas))) @s.define class Thing: x = int schemas.append(s) #create a new database for this new schema and subscribe in both this one and #the main connection dbs.append(self.createNewDb()) dbs[-1].subscribeToSchema(s) db.subscribeToSchema(s) #create a new object in the schema things = [] for i in range(len(schemas)): with dbs[i].transaction(): things.append(schemas[i].Thing(x=10)) #make sure that the main db sees it for thing in things: db.waitForCondition(lambda: thing.exists(), 10 * self.PERFORMANCE_FACTOR) #verify the main db sees something quadratic in the number of transactions plus a constant self.assertLess(db._messages_received, (len(schemas) + 1) * (len(schemas) + 2) + 8) #each database sees two transactions each pass for i in range(len(dbs)): self.assertTrue( dbs[i]._messages_received < (len(schemas) - i) * 2 + 10)
def test_freezing_schema_with_undefined_fails(self): schema = Schema("test_schema") @schema.define class Object: x = schema.Object2 y = int with self.assertRaises(Exception): schema.freeze() @schema.define class Object2: x = int schema.freeze()
def test_subclassing(self): schema = Schema("schema") @schema.define class Test: i = int def f(self): return 1 def g(self): return 2 @schema.define class SubclassTesting(Test): y = int def g(self): return 3 def h(self): return 4 db = self.createNewDb() db.subscribeToSchema(schema) with db.transaction(): t = Test(i=1) t2 = SubclassTesting(i=2, y=3) self.assertEqual(t.f(), 1) self.assertEqual(t.g(), 2) self.assertEqual(t2.f(), 1) self.assertEqual(t2.g(), 3) self.assertEqual(t2.h(), 4) self.assertEqual(t2.y, 3)
def test_read_write_conflict(self): db = self.createNewDb() schema = Schema("test_schema") @schema.define class Counter: k = int db.subscribeToSchema(schema) with db.transaction(): o1 = Counter() o2 = Counter() for consistency in [True, False]: if consistency: t1 = db.transaction().consistency(reads=True) t2 = db.transaction().consistency(reads=True) else: t1 = db.transaction().consistency(none=True) t2 = db.transaction().consistency(none=True) with t1.nocommit(): o1.k = o2.k + 1 with t2.nocommit(): o2.k = o1.k + 1 t1.commit() if consistency: with self.assertRaises(RevisionConflictException): t2.commit() else: t2.commit()
from object_database.schema import Schema core_schema = Schema("core") @core_schema.define class Connection: pass
from object_database.schema import Indexed, Index, Schema from object_database.core_schema import core_schema from object_database.view import RevisionConflictException, DisconnectedException, ObjectDoesntExistException from object_database.database_connection import TransactionListener, DatabaseConnection from object_database.tcp_server import TcpServer, connect from object_database.inmem_server import InMemServer from object_database.persistence import InMemoryPersistence, RedisPersistence from object_database.util import genToken import unittest import numpy import threading from object_database.util import configureLogging schema = Schema("test_schema") @schema.define class Ring: left = Indexed(OneOf(None, schema.Ring)) right = Indexed(OneOf(None, schema.Ring)) k = Indexed(int) @staticmethod def New(): r = Ring() r.left = r.right = r return r def insert(self, k):
def waitForCallback(self, timeout): return self.callbackArgs.get(timeout=timeout) def releaseCallback(self): self.is_released.put(True) expr = Alternative( "Expr", Constant={'value': int}, #Add = {'l': expr, 'r': expr}, #Sub = {'l': expr, 'r': expr}, #Mul = {'l': expr, 'r': expr} ) schema = Schema("test_schema") schema.expr = expr @schema.define class Root: obj = OneOf(None, schema.Object) k = int @schema.define class Object: k = Indexed(expr) other = OneOf(None, schema.Object) @property