-- SchemaTest.mesa
-- Last edited by:
-- John Maxwell on May 14, 1982 10:11 am
-- Rick Cattell on May 22, 1982 7:11 pm
-- DBView problems:
-- No DestroySubType (in TestSubType)
-- No DestroyAttribute (in TestAttribute)
-- GetEntityByName[DomainDomain, "DomainDomain"] => NotFound
-- Renaming doesn't work
-- KeyPart not implemented
-- this program does not test:
-- nameType in DeclareDomain
-- version parameter in DeclareX[ . . . version: Version]
-- RecordType
-- enforcement of uniqueness on Attributes and Properties
-- runtime type-checking on Attributes and Properties
-- length properties on Attributes and Properties
-- DeclarePropertyFromAttrs
-- Anything to do with Relships or Entities
-- Transactions with the Database (open, close, mark . . .)
DIRECTORY
DBView,
IOStream,
Process USING [Detach],
Rope USING [Equal, ROPE];
SchemaTest: PROGRAM
IMPORTS DBView, IOStream, Process, Rope =
BEGIN
OPEN DBView;
ROPE: TYPE = Rope.ROPE;
tty: IOStream.Handle← IOStream.CreateTTYStreams["SchemaTest.log"].out;
TestAll: PROCEDURE =
BEGIN
Thing: Domain;
Animal: Domain;
Person: Domain;
legalName: Property;
ssNumber: Property;
alive, any, father: Property;
friend: Relation;
of, is, for: Attribute;
closeness, oppositeSex: Attribute;
tty.PutF["Opening [Local]Test...\n"];
[]← OpenDatabase[databaseName: "[Local]Test", version: NewOnly];
Thing ← TestDomain["Thing"];
Animal ← TestDomain["Animal"];
TestSubType[Animal, Thing];
Person ← TestDomain["Person"];
TestSubType[Person, Animal];
-- test properties
tty.PutF["Testing properties...\n"];
any ← TestProperty["anything", Person, AnyDomainType, None];
father ← TestProperty["father", Person, Person, Key];
legalName ← TestProperty["legalName", Person, StringType, Key];
ssNumber ← TestProperty["ssNumber", Person, IntType, OptionalKey];
alive ← TestProperty["alive", Person, BoolType, None];
-- test attributes
tty.PutF["Testing relations...\n"];
friend ← TestRelation["friend"];
tty.PutF["Testing attributes...\n"];
is ← TestAttribute[friend, "is", AnyDomainType, None];
of ← TestAttribute[friend, "of", Person, Key];
closeness ← TestAttribute[friend, "closeness", StringType, Key];
for ← TestAttribute[friend, "for", IntType, OptionalKey];
oppositeSex ← TestAttribute[friend, "oppositeSex", BoolType, None];
tty.PutF["Testing domains...\n"];
TestDataTypeDomain[];
tty.PutF["Testing domain domain...\n"];
TestDomainDomain[];
tty.PutF["Closing database...\n"];
CloseDatabase[];
END;
TestDomainDomain: PROCEDURE =
BEGIN -- no guarantees that this is correct
IF DomainOf[DomainDomain] # DomainDomain THEN ERROR;
IF DomainOf[RelationDomain] # DomainDomain THEN ERROR;
IF DomainOf[AttributeDomain] # DomainDomain THEN ERROR;
IF DomainOf[DataTypeDomain] # DomainDomain THEN ERROR;
TestGet[DomainDomain, DomainDomain, "Domain"];
TestGet[DomainDomain, RelationDomain, "Relation"];
TestGet[DomainDomain, AttributeDomain, "Attribute"];
TestGet[DomainDomain, DataTypeDomain, "DataType"];
END;
TestDataTypeDomain: PROCEDURE =
BEGIN -- no guarantees that this is correct
IF DomainOf[StringType] # DataTypeDomain THEN ERROR;
IF DomainOf[IntType] # DataTypeDomain THEN ERROR;
IF DomainOf[BoolType] # DataTypeDomain THEN ERROR;
IF DomainOf[RecordType] # DataTypeDomain THEN ERROR;
IF DomainOf[AnyDomainType] # DataTypeDomain THEN ERROR;
TestGet[DataTypeDomain, StringType, "StringType"];
TestGet[DataTypeDomain, IntType, "IntType"];
TestGet[DataTypeDomain, BoolType, "BoolType"];
END;
TestDomain: PROCEDURE[name: ROPE] RETURNS[d: Domain] =
BEGIN -- tests declaring, destroying, and renaming
d ← DeclareDomain[name];
TestGet[DomainDomain, d, name];
DestroyDomain[d];
TestNotFound[DomainDomain, d, name];
d ← DeclareDomain[name];
TestGet[DomainDomain, d, name];
TestRename[DomainDomain, d, name];
END;
TestSubType: PROCEDURE[sub, super: Domain] =
BEGIN
DeclareSubType[of: super, is: sub];
IF ~SubType[sub, super] THEN ERROR;
IF SubType[super, sub] THEN ERROR;
DestroySubType[of: super, is: sub];
IF SubType[sub, super] THEN ERROR;
DeclareSubType[of: super, is: sub];
IF ~SubType[sub, super] THEN ERROR;
IF SubType[super, sub] THEN ERROR;
END;
TestRelation: PROCEDURE[name: ROPE] RETURNS[r: Relation] =
BEGIN -- tests declaring, destroying, and renaming
r ← DeclareRelation[name];
TestGet[RelationDomain, r, name];
DestroyRelation[r];
TestNotFound[RelationDomain, r, name];
r ← DeclareRelation[name];
TestRename[RelationDomain, r, name];
END;
TestAttribute: PROCEDURE[r: Relation, name: ROPE, type: DataType, uniqueness: Uniqueness]
RETURNS[a: Attribute] =
BEGIN
a ← DeclareAttribute[r, name, type, uniqueness];
TestGetAttribute[r, a];
IF ~Eq[V2E[GetP[a, aRelationProp]], r] THEN ERROR;
IF ~Eq[V2E[GetP[a, aTypeProp]], type] THEN ERROR;
IF V2U[GetP[a, aUniquenessProp]] # uniqueness THEN ERROR;
-- DestroyAttribute[a];
-- TestNotFound[AttributeDomain, a, name];
-- a ← DeclareAttribute[r, name, type, uniqueness];
-- TestGet[AttributeDomain, a, name];
-- TestRename[AttributeDomain, a, name];
END;
TestProperty: PROCEDURE[name: ROPE, of: Domain, is: DataType, u: Uniqueness]
RETURNS[p: Property] =
BEGIN
r: Relation;
a: Attribute;
key: Uniqueness ← Key;
attributes: AttributeList;
p ← DeclareProperty[name, of, is, u];
r ← GetEntityByName[RelationDomain, name];
attributes ← AttributesOf[r];
FOR list: AttributeList ← attributes, list.rest WHILE list # NIL DO
a ← list.first;
SELECT TRUE FROM
Rope.Equal[GetName[a], "of"] => {
IF ~Eq[V2E[GetP[a, aRelationProp]], r] THEN ERROR;
IF ~Eq[V2E[GetP[a, aTypeProp]], of] THEN ERROR;
IF V2U[GetP[a, aUniquenessProp]] # key THEN ERROR};
Rope.Equal[GetName[a], "is"] => {
IF ~Eq[V2E[GetP[a, aRelationProp]], r] THEN ERROR;
IF ~Eq[V2E[GetP[a, aTypeProp]], is] THEN ERROR;
IF V2U[GetP[a, aUniquenessProp]] # u THEN ERROR};
ENDCASE => ERROR;
ENDLOOP;
END;
SubType: PROCEDURE[sub, super: Domain] RETURNS[BOOLEAN] =
BEGIN
rs: RelshipSet;
subRS: Relship;
IF Eq[sub, super] THEN RETURN[TRUE];
rs ← RelationSubset[SubTypeRelation, LIST[[sSubType, sub]]];
WHILE (subRS ← NextRelship[rs]) # NIL DO
IF SubType[super, V2E[GetF[subRS, sSuperType]]] THEN RETURN[TRUE];
ENDLOOP;
ReleaseRelshipSet[rs];
RETURN[FALSE];
END;
TestRename: PROCEDURE[d: Domain, e: Entity, name: ROPE] =
BEGIN
SetName[e, "Any"];
TestGet[d, e, "Any"];
TestNotFound[d, NIL, name];
SetName[e, name];
TestGet[d, e, name];
TestNotFound[d, NIL, "Any"];
END;
TestGet: PROCEDURE[d: Domain, e: Entity, name: ROPE] =
BEGIN
temp: Entity;
temp ← GetEntityByName[d, name];
IF ~Eq[temp, e] THEN ERROR;
IF ~Rope.Equal[GetName[e], name] THEN ERROR;
END;
TestGetAttribute: PROCEDURE[r: Relation, a: Attribute] =
BEGIN
attributes: AttributeList;
attributes ← AttributesOf[r];
FOR list: AttributeList ← attributes, list.rest WHILE list # NIL DO
IF ~Eq[list.first, a] THEN LOOP;
RETURN; ENDLOOP;
ERROR;
END;
TestNotFound: PROCEDURE[d: Domain, e: Entity, name: ROPE] =
BEGIN
temp: Entity;
signal: BOOLEAN ← FALSE;
temp ← GetEntityByName[d, name ! NotFound => {signal ← TRUE; CONTINUE}];
IF ~signal THEN ERROR;
IF e # NIL AND ~Null[e] THEN ERROR;
END;
AttributesOf: PROC[r: Relation] RETURNS[AttributeList] =
{RETURN[EntitySetToList[DomainSubset[AttributeDomain, LIST[[aRelationProp, r]]]]]};
Process.Detach[FORK TestAll[]];
END.