Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add test codifying import dynamic schema behavior #137

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/performance-tests/test/iModelUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { BriefcaseIdValue, Code } from "@itwin/core-common";
import { initOutputFile } from "./TestUtils";
import { Point3d, YawPitchRollAngles } from "@itwin/core-geometry";
import { IModelTransformerTestUtils } from "@itwin/imodel-transformer/lib/cjs/test/IModelTransformerUtils";
import { getTShirtSizeFromName, TestIModel } from "./TestContext";
import { getTShirtSizeFromName, TestIModel } from "./TestContext";

const outputDir = path.join(__dirname, ".output");

Expand All @@ -27,7 +27,9 @@ export function setToStandalone(iModelPath: string) {
nativeDb.resetBriefcaseId(BriefcaseIdValue.Unassigned); // standalone iModels should always have BriefcaseId unassigned
nativeDb.saveLocalValue("StandaloneEdit", JSON.stringify({ txns: true }));
nativeDb.saveChanges(); // save change to briefcaseId
nativeDb.closeIModel();
// handle cross-version usage of internal API
(nativeDb as any)?.closeIModel();
(nativeDb as any)?.closeFile();
}

export function generateTestIModel(iModelParam: IModelParams): TestIModel {
Expand Down
103 changes: 101 additions & 2 deletions packages/transformer/src/test/standalone/IModelTransformer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1089,7 +1089,9 @@ describe("IModelTransformer", () => {
nativeDb.resetBriefcaseId(BriefcaseIdValue.Unassigned); // standalone iModels should always have BriefcaseId unassigned
nativeDb.saveLocalValue("StandaloneEdit", JSON.stringify({ txns: true }));
nativeDb.saveChanges(); // save change to briefcaseId
nativeDb.closeIModel();
// handle cross-version usage of internal API
(nativeDb as any)?.closeIModel();
(nativeDb as any)?.closeFile();
}

it("biscore update is valid", async () => {
Expand All @@ -1108,7 +1110,9 @@ describe("IModelTransformer", () => {
// StandaloneDb.upgradeStandaloneSchemas is the suggested method to handle a profile upgrade but that will also upgrade
// the BisCore schema. This test is explicitly testing that the BisCore schema will be updated from the source iModel
const nativeDb = StandaloneDb.openDgnDb({path: targetDbPath}, OpenMode.ReadWrite, {profile: ProfileOptions.Upgrade, schemaLockHeld: true});
nativeDb.closeIModel();
// handle cross-version usage of internal API
(nativeDb as any)?.closeIModel();
(nativeDb as any)?.closeFile();
const targetDb = StandaloneDb.openFile(targetDbPath);

assert(
Expand Down Expand Up @@ -2746,6 +2750,101 @@ describe("IModelTransformer", () => {
targetDb.close();
});

it("try import dynamic schemas regardless of version", async function () {
const makeDynamicSchema = (version: string, classes = [] as string[]) => `<?xml version="1.0" encoding="UTF-8"?>
<ECSchema schemaName="Dynamic" alias="d1" version="${version}" displayLabel="dyn" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
<ECCustomAttributes>
<DynamicSchema xmlns="CoreCustomAttributes.01.00.03"/>
</ECCustomAttributes>
<ECSchemaReference name="BisCore" version="01.00.00" alias="bis"/>
${classes.map((c) => `
<ECEntityClass typeName="${c}">
<BaseClass>bis:PhysicalElement</BaseClass>
<ECProperty propertyName="MyProp1" typeName="string"/>
</ECEntityClass>
`)}
</ECSchema>
`;

const targetDbFile: string = IModelTransformerTestUtils.prepareOutputFile("IModelTransformer", "DynSchemas2-Target.bim");
const targetDb = SnapshotDb.createEmpty(targetDbFile, { rootSubject: { name: "DynSchemasTarget" } });
const targetVersion = "01.10.00";
await targetDb.importSchemaStrings([makeDynamicSchema(targetVersion, ["A"])]);
targetDb.saveChanges();
expect(() => targetDb.getMetaData("d1:A")).not.to.throw();

const unpadVersion = (v: string) => v.split(".").map(Number).join(".");

// try import lesser version dynamic schema
{
const sourceDbFile = IModelTransformerTestUtils.prepareOutputFile("IModelTransformer", "DynSchemas2-Source.bim");
const sourceDb = SnapshotDb.createEmpty(sourceDbFile, { rootSubject: { name: "DynSchemaSource" } });
const lesserVersion = "01.07.00";
expect(Semver.lt(unpadVersion(lesserVersion), unpadVersion(targetVersion))).to.be.true;
await sourceDb.importSchemaStrings([makeDynamicSchema(lesserVersion, ["A", "B"])]);
sourceDb.saveChanges();

const transformer = new IModelTransformer(sourceDb, targetDb);
// expect this to not reject, adding chai as promised makes the error less readable
await transformer.processSchemas();

transformer.dispose();
sourceDb.close();

expect(targetDb.querySchemaVersion("Dynamic")).to.equal(unpadVersion(targetVersion));
expect(() => targetDb.getMetaData("d1:A")).not.to.throw();
// schema be not be exported because <= version
expect(() => targetDb.getMetaData("d1:B")).to.throw();
}

// try import equal version schema
{
const sourceDbFile = IModelTransformerTestUtils.prepareOutputFile("IModelTransformer", "DynSchemas2-Source2.bim");
const sourceDb = SnapshotDb.createEmpty(sourceDbFile, { rootSubject: { name: "DynSchemaSource2" } });
await sourceDb.importSchemaStrings([makeDynamicSchema(targetVersion, ["A", "B", "C"])]);
sourceDb.saveChanges();

const transformer = new IModelTransformer(sourceDb, targetDb);
// expect this to not reject, adding chai as promised makes the error less readable
await transformer.processSchemas();

transformer.dispose();
sourceDb.close();

expect(targetDb.querySchemaVersion("Dynamic")).to.equal(unpadVersion(targetVersion));
expect(() => targetDb.getMetaData("d1:A")).not.to.throw();
// schema be not be exported because <= version
expect(() => targetDb.getMetaData("d1:B")).to.throw();
expect(() => targetDb.getMetaData("d1:C")).to.throw();
}

// try import later dynamic schema
{
const sourceDbFile = IModelTransformerTestUtils.prepareOutputFile("IModelTransformer", "DynSchemas2-Source3.bim");
const sourceDb = SnapshotDb.createEmpty(sourceDbFile, { rootSubject: { name: "DynSchemaSource3" } });
const greaterVersion = "01.11.00";
expect(Semver.gt(unpadVersion(greaterVersion), unpadVersion(targetVersion))).to.be.true;
await sourceDb.importSchemaStrings([makeDynamicSchema(greaterVersion, ["A", "B", "C", "D"])]);
sourceDb.saveChanges();

const transformer = new IModelTransformer(sourceDb, targetDb);
// expect this to not reject, adding chai as promised makes the error less readable
await transformer.processSchemas();

transformer.dispose();
sourceDb.close();

expect(targetDb.querySchemaVersion("Dynamic")).to.equal(unpadVersion(greaterVersion));
// schema will be exported and merged by ECDb because > version
expect(() => targetDb.getMetaData("d1:A")).not.to.throw();
expect(() => targetDb.getMetaData("d1:B")).not.to.throw();
expect(() => targetDb.getMetaData("d1:C")).not.to.throw();
expect(() => targetDb.getMetaData("d1:D")).not.to.throw();
}

targetDb.close();
});

/** unskip to generate a javascript CPU profile on just the processAll portion of an iModel */
it.skip("should profile an IModel transformation", async function () {
const sourceDbFile = IModelTransformerTestUtils.prepareOutputFile("IModelTransformer", "ProfileTransformation.bim");
Expand Down
Loading