@itwin/core-backend 5.13.0-dev.9 → 5.14.0-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +33 -1
- package/lib/cjs/Category.d.ts +4 -4
- package/lib/cjs/Category.js.map +1 -1
- package/lib/cjs/ChangesetECAdaptor.d.ts +5 -0
- package/lib/cjs/ChangesetECAdaptor.d.ts.map +1 -1
- package/lib/cjs/ChangesetECAdaptor.js +13 -3
- package/lib/cjs/ChangesetECAdaptor.js.map +1 -1
- package/lib/cjs/CodeSpecs.d.ts +3 -3
- package/lib/cjs/CodeSpecs.js.map +1 -1
- package/lib/cjs/DisplayStyle.d.ts +2 -2
- package/lib/cjs/DisplayStyle.js.map +1 -1
- package/lib/cjs/EditTxn.d.ts.map +1 -1
- package/lib/cjs/EditTxn.js +1 -0
- package/lib/cjs/EditTxn.js.map +1 -1
- package/lib/cjs/Element.d.ts +48 -12
- package/lib/cjs/Element.d.ts.map +1 -1
- package/lib/cjs/Element.js +120 -24
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +30 -15
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +51 -15
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/Model.d.ts +5 -5
- package/lib/cjs/Model.d.ts.map +1 -1
- package/lib/cjs/Model.js.map +1 -1
- package/lib/cjs/PropertyStore.js +1 -1
- package/lib/cjs/PropertyStore.js.map +1 -1
- package/lib/cjs/SchemaSync.d.ts +37 -9
- package/lib/cjs/SchemaSync.d.ts.map +1 -1
- package/lib/cjs/SchemaSync.js +125 -6
- package/lib/cjs/SchemaSync.js.map +1 -1
- package/lib/cjs/SynchronousChannel.d.ts +62 -0
- package/lib/cjs/SynchronousChannel.d.ts.map +1 -0
- package/lib/cjs/SynchronousChannel.js +11 -0
- package/lib/cjs/SynchronousChannel.js.map +1 -0
- package/lib/cjs/Texture.d.ts +1 -1
- package/lib/cjs/Texture.js.map +1 -1
- package/lib/cjs/TxnManager.d.ts +44 -4
- package/lib/cjs/TxnManager.d.ts.map +1 -1
- package/lib/cjs/TxnManager.js +72 -14
- package/lib/cjs/TxnManager.js.map +1 -1
- package/lib/cjs/ViewDefinition.d.ts +6 -6
- package/lib/cjs/ViewDefinition.d.ts.map +1 -1
- package/lib/cjs/ViewDefinition.js.map +1 -1
- package/lib/cjs/annotations/LeaderGeometry.d.ts +22 -7
- package/lib/cjs/annotations/LeaderGeometry.d.ts.map +1 -1
- package/lib/cjs/annotations/LeaderGeometry.js +104 -36
- package/lib/cjs/annotations/LeaderGeometry.js.map +1 -1
- package/lib/cjs/annotations/TextAnnotationElement.d.ts +1 -1
- package/lib/cjs/annotations/TextAnnotationElement.d.ts.map +1 -1
- package/lib/cjs/annotations/TextAnnotationElement.js +25 -10
- package/lib/cjs/annotations/TextAnnotationElement.js.map +1 -1
- package/lib/cjs/core-backend.d.ts +1 -0
- package/lib/cjs/core-backend.d.ts.map +1 -1
- package/lib/cjs/core-backend.js +1 -0
- package/lib/cjs/core-backend.js.map +1 -1
- package/lib/cjs/internal/IntegrityCheck.d.ts +22 -0
- package/lib/cjs/internal/IntegrityCheck.d.ts.map +1 -1
- package/lib/cjs/internal/IntegrityCheck.js +13 -0
- package/lib/cjs/internal/IntegrityCheck.js.map +1 -1
- package/lib/cjs/internal/NoReservations.d.ts +6 -0
- package/lib/cjs/internal/NoReservations.d.ts.map +1 -0
- package/lib/cjs/internal/NoReservations.js +21 -0
- package/lib/cjs/internal/NoReservations.js.map +1 -0
- package/lib/cjs/internal/SchemaSyncReservations.d.ts +4 -0
- package/lib/cjs/internal/SchemaSyncReservations.d.ts.map +1 -0
- package/lib/cjs/internal/SchemaSyncReservations.js +118 -0
- package/lib/cjs/internal/SchemaSyncReservations.js.map +1 -0
- package/lib/cjs/internal/Symbols.d.ts +1 -0
- package/lib/cjs/internal/Symbols.d.ts.map +1 -1
- package/lib/cjs/internal/Symbols.js +2 -1
- package/lib/cjs/internal/Symbols.js.map +1 -1
- package/lib/esm/Category.d.ts +4 -4
- package/lib/esm/Category.js.map +1 -1
- package/lib/esm/ChangesetECAdaptor.d.ts +5 -0
- package/lib/esm/ChangesetECAdaptor.d.ts.map +1 -1
- package/lib/esm/ChangesetECAdaptor.js +13 -3
- package/lib/esm/ChangesetECAdaptor.js.map +1 -1
- package/lib/esm/CodeSpecs.d.ts +3 -3
- package/lib/esm/CodeSpecs.js.map +1 -1
- package/lib/esm/DisplayStyle.d.ts +2 -2
- package/lib/esm/DisplayStyle.js.map +1 -1
- package/lib/esm/EditTxn.d.ts.map +1 -1
- package/lib/esm/EditTxn.js +1 -0
- package/lib/esm/EditTxn.js.map +1 -1
- package/lib/esm/Element.d.ts +48 -12
- package/lib/esm/Element.d.ts.map +1 -1
- package/lib/esm/Element.js +121 -25
- package/lib/esm/Element.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +30 -15
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +52 -16
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/Model.d.ts +5 -5
- package/lib/esm/Model.d.ts.map +1 -1
- package/lib/esm/Model.js.map +1 -1
- package/lib/esm/PropertyStore.js +1 -1
- package/lib/esm/PropertyStore.js.map +1 -1
- package/lib/esm/SchemaSync.d.ts +37 -9
- package/lib/esm/SchemaSync.d.ts.map +1 -1
- package/lib/esm/SchemaSync.js +127 -8
- package/lib/esm/SchemaSync.js.map +1 -1
- package/lib/esm/SynchronousChannel.d.ts +62 -0
- package/lib/esm/SynchronousChannel.d.ts.map +1 -0
- package/lib/esm/SynchronousChannel.js +9 -0
- package/lib/esm/SynchronousChannel.js.map +1 -0
- package/lib/esm/Texture.d.ts +1 -1
- package/lib/esm/Texture.js.map +1 -1
- package/lib/esm/TxnManager.d.ts +44 -4
- package/lib/esm/TxnManager.d.ts.map +1 -1
- package/lib/esm/TxnManager.js +72 -14
- package/lib/esm/TxnManager.js.map +1 -1
- package/lib/esm/ViewDefinition.d.ts +6 -6
- package/lib/esm/ViewDefinition.d.ts.map +1 -1
- package/lib/esm/ViewDefinition.js.map +1 -1
- package/lib/esm/annotations/LeaderGeometry.d.ts +22 -7
- package/lib/esm/annotations/LeaderGeometry.d.ts.map +1 -1
- package/lib/esm/annotations/LeaderGeometry.js +104 -36
- package/lib/esm/annotations/LeaderGeometry.js.map +1 -1
- package/lib/esm/annotations/TextAnnotationElement.d.ts +1 -1
- package/lib/esm/annotations/TextAnnotationElement.d.ts.map +1 -1
- package/lib/esm/annotations/TextAnnotationElement.js +25 -10
- package/lib/esm/annotations/TextAnnotationElement.js.map +1 -1
- package/lib/esm/core-backend.d.ts +1 -0
- package/lib/esm/core-backend.d.ts.map +1 -1
- package/lib/esm/core-backend.js +1 -0
- package/lib/esm/core-backend.js.map +1 -1
- package/lib/esm/internal/IntegrityCheck.d.ts +22 -0
- package/lib/esm/internal/IntegrityCheck.d.ts.map +1 -1
- package/lib/esm/internal/IntegrityCheck.js +13 -0
- package/lib/esm/internal/IntegrityCheck.js.map +1 -1
- package/lib/esm/internal/NoReservations.d.ts +6 -0
- package/lib/esm/internal/NoReservations.d.ts.map +1 -0
- package/lib/esm/internal/NoReservations.js +18 -0
- package/lib/esm/internal/NoReservations.js.map +1 -0
- package/lib/esm/internal/SchemaSyncReservations.d.ts +4 -0
- package/lib/esm/internal/SchemaSyncReservations.d.ts.map +1 -0
- package/lib/esm/internal/SchemaSyncReservations.js +115 -0
- package/lib/esm/internal/SchemaSyncReservations.js.map +1 -0
- package/lib/esm/internal/Symbols.d.ts +1 -0
- package/lib/esm/internal/Symbols.d.ts.map +1 -1
- package/lib/esm/internal/Symbols.js +1 -0
- package/lib/esm/internal/Symbols.js.map +1 -1
- package/lib/esm/test/IModelTestUtils.d.ts +1 -1
- package/lib/esm/test/IModelTestUtils.d.ts.map +1 -1
- package/lib/esm/test/IModelTestUtils.js +8 -3
- package/lib/esm/test/IModelTestUtils.js.map +1 -1
- package/lib/esm/test/annotations/LeaderGeometry.test.js +178 -2
- package/lib/esm/test/annotations/LeaderGeometry.test.js.map +1 -1
- package/lib/esm/test/annotations/TextAnnotation.test.js +48 -18
- package/lib/esm/test/annotations/TextAnnotation.test.js.map +1 -1
- package/lib/esm/test/ecdb/ECSqlStatement.test.js +177 -0
- package/lib/esm/test/ecdb/ECSqlStatement.test.js.map +1 -1
- package/lib/esm/test/ecdb/QueryReaders.test.js +2 -16
- package/lib/esm/test/ecdb/QueryReaders.test.js.map +1 -1
- package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js +2 -2
- package/lib/esm/test/ecsql/src/ECSqlTestRunner.test.js.map +1 -1
- package/lib/esm/test/element/ElementRoundTrip.test.js +80 -2
- package/lib/esm/test/element/ElementRoundTrip.test.js.map +1 -1
- package/lib/esm/test/imodel/IModelECSql.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelECSql.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelECSql.test.js +367 -0
- package/lib/esm/test/imodel/IModelECSql.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelElements.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelElements.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelElements.test.js +969 -0
- package/lib/esm/test/imodel/IModelElements.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelGeolocation.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelGeolocation.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelGeolocation.test.js +539 -0
- package/lib/esm/test/imodel/IModelGeolocation.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelLifecycle.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelLifecycle.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelLifecycle.test.js +499 -0
- package/lib/esm/test/imodel/IModelLifecycle.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelMetadata.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelMetadata.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelMetadata.test.js +274 -0
- package/lib/esm/test/imodel/IModelMetadata.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelModels.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelModels.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelModels.test.js +357 -0
- package/lib/esm/test/imodel/IModelModels.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelRelationships.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelRelationships.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelRelationships.test.js +407 -0
- package/lib/esm/test/imodel/IModelRelationships.test.js.map +1 -0
- package/lib/esm/test/imodel/IModelTestFixtures.d.ts +53 -0
- package/lib/esm/test/imodel/IModelTestFixtures.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelTestFixtures.js +107 -0
- package/lib/esm/test/imodel/IModelTestFixtures.js.map +1 -0
- package/lib/esm/test/imodel/IModelViews.test.d.ts +2 -0
- package/lib/esm/test/imodel/IModelViews.test.d.ts.map +1 -0
- package/lib/esm/test/imodel/IModelViews.test.js +199 -0
- package/lib/esm/test/imodel/IModelViews.test.js.map +1 -0
- package/lib/esm/test/index.d.ts +0 -1
- package/lib/esm/test/index.d.ts.map +1 -1
- package/lib/esm/test/index.js +0 -1
- package/lib/esm/test/index.js.map +1 -1
- package/lib/esm/test/standalone/ChangesetReader.test.js +8 -26
- package/lib/esm/test/standalone/ChangesetReader.test.js.map +1 -1
- package/lib/esm/test/standalone/DgnDomainMergeConflict.test.d.ts +2 -0
- package/lib/esm/test/standalone/DgnDomainMergeConflict.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/DgnDomainMergeConflict.test.js +263 -0
- package/lib/esm/test/standalone/DgnDomainMergeConflict.test.js.map +1 -0
- package/lib/esm/test/standalone/GeometryStream.test.js +1 -3
- package/lib/esm/test/standalone/GeometryStream.test.js.map +1 -1
- package/lib/esm/test/standalone/IModelWrite.test.d.ts.map +1 -1
- package/lib/esm/test/standalone/IModelWrite.test.js +78 -1
- package/lib/esm/test/standalone/IModelWrite.test.js.map +1 -1
- package/lib/esm/test/standalone/IntegrityCheck.test.js +29 -10
- package/lib/esm/test/standalone/IntegrityCheck.test.js.map +1 -1
- package/lib/esm/test/standalone/SQliteChangesetReaderAndChangesetECAdaptor.test.js +23 -0
- package/lib/esm/test/standalone/SQliteChangesetReaderAndChangesetECAdaptor.test.js.map +1 -1
- package/lib/esm/test/standalone/SchemaSyncDb.test.d.ts +2 -0
- package/lib/esm/test/standalone/SchemaSyncDb.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/SchemaSyncDb.test.js +221 -0
- package/lib/esm/test/standalone/SchemaSyncDb.test.js.map +1 -0
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.d.ts +2 -0
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.d.ts.map +1 -0
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js +459 -0
- package/lib/esm/test/standalone/SchemaSyncElementReservation.test.js.map +1 -0
- package/lib/esm/test/standalone/SnapshotDb.test.js +1 -0
- package/lib/esm/test/standalone/SnapshotDb.test.js.map +1 -1
- package/lib/esm/test/standalone/TxnManager.test.js +108 -8
- package/lib/esm/test/standalone/TxnManager.test.js.map +1 -1
- package/package.json +14 -17
- package/lib/esm/test/RevisionUtility.d.ts +0 -33
- package/lib/esm/test/RevisionUtility.d.ts.map +0 -1
- package/lib/esm/test/RevisionUtility.js +0 -52
- package/lib/esm/test/RevisionUtility.js.map +0 -1
- package/lib/esm/test/imodel/IModel.test.d.ts +0 -2
- package/lib/esm/test/imodel/IModel.test.d.ts.map +0 -1
- package/lib/esm/test/imodel/IModel.test.js +0 -3277
- package/lib/esm/test/imodel/IModel.test.js.map +0 -1
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
/*---------------------------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
|
|
3
|
+
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
|
+
*--------------------------------------------------------------------------------------------*/
|
|
5
|
+
import { assert, expect } from "chai";
|
|
6
|
+
import * as semver from "semver";
|
|
7
|
+
import * as sinon from "sinon";
|
|
8
|
+
import { DbResult, Guid, Id64, IModelStatus, Logger, OpenMode } from "@itwin/core-bentley";
|
|
9
|
+
import { BriefcaseIdValue, Code, EcefLocation, IModel, IModelError, SchemaState, SubCategoryAppearance } from "@itwin/core-common";
|
|
10
|
+
import { ECVersion } from "@itwin/ecschema-metadata";
|
|
11
|
+
import { V2CheckpointManager } from "../../CheckpointManager";
|
|
12
|
+
import { EditTxn, withEditTxn } from "../../EditTxn";
|
|
13
|
+
import { GenericGraphicalType2d, IModelDb, IModelHost, IModelJsFs, PhysicalModel, PhysicalObject, SnapshotDb, SpatialCategory, StandaloneDb } from "../../core-backend";
|
|
14
|
+
import { BriefcaseDb } from "../../IModelDb";
|
|
15
|
+
import { HubMock } from "../../internal/HubMock";
|
|
16
|
+
import { _cache, _hubAccess, _instanceKeyCache, _nativeDb } from "../../internal/Symbols";
|
|
17
|
+
import { IModelTestUtils } from "../IModelTestUtils";
|
|
18
|
+
import { TestUtils } from "../TestUtils";
|
|
19
|
+
import { performance } from "perf_hooks";
|
|
20
|
+
import { createIModelFromSeed, expectIModelError, getIModelError, importTestBim } from "./IModelTestFixtures";
|
|
21
|
+
describe("iModel lifecycle", () => {
|
|
22
|
+
let originalEnv;
|
|
23
|
+
before(async () => {
|
|
24
|
+
originalEnv = { ...process.env };
|
|
25
|
+
await TestUtils.startBackend();
|
|
26
|
+
IModelTestUtils.registerTestBimSchema();
|
|
27
|
+
});
|
|
28
|
+
after(() => {
|
|
29
|
+
process.env = originalEnv;
|
|
30
|
+
});
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
sinon.restore();
|
|
33
|
+
});
|
|
34
|
+
function hasClassView(db, name) {
|
|
35
|
+
try {
|
|
36
|
+
return db.withSqliteStatement(`SELECT ECInstanceId FROM [${name}]`, () => true, false);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
it("should be able to create a snapshot IModel", async () => {
|
|
43
|
+
const args = {
|
|
44
|
+
rootSubject: { name: "TestSubject", description: "test iTwin" },
|
|
45
|
+
client: "ABC Engineering",
|
|
46
|
+
globalOrigin: { x: 10, y: 10 },
|
|
47
|
+
projectExtents: { low: { x: -300, y: -300, z: -20 }, high: { x: 500, y: 500, z: 400 } },
|
|
48
|
+
guid: Guid.createValue(),
|
|
49
|
+
};
|
|
50
|
+
const iModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IModel", "TestSnapshot.bim"), args);
|
|
51
|
+
assert.equal(iModel.iModelId, args.guid);
|
|
52
|
+
assert.equal(iModel.rootSubject.name, args.rootSubject.name);
|
|
53
|
+
assert.equal(iModel.rootSubject.description, args.rootSubject.description);
|
|
54
|
+
assert.equal(iModel.projectExtents.low.x, args.projectExtents.low.x);
|
|
55
|
+
assert.equal(iModel.projectExtents.low.y, args.projectExtents.low.y);
|
|
56
|
+
assert.equal(iModel.projectExtents.low.z, args.projectExtents.low.z);
|
|
57
|
+
assert.equal(iModel.globalOrigin.x, args.globalOrigin.x);
|
|
58
|
+
assert.equal(iModel.globalOrigin.y, args.globalOrigin.y);
|
|
59
|
+
assert.equal(iModel.globalOrigin.z, 0);
|
|
60
|
+
const client = iModel.queryFilePropertyString({ name: "Client", namespace: "dgn_Db" });
|
|
61
|
+
assert.equal(client, args.client, "query Client property");
|
|
62
|
+
const dbguid = iModel.queryFilePropertyBlob({ name: "DbGuid", namespace: "be_Db" });
|
|
63
|
+
assert.equal(dbguid.byteLength, 16, "query guid property");
|
|
64
|
+
const myPropsStr = { name: "MyProp", namespace: "test1", id: 1, subId: 1 };
|
|
65
|
+
const myStrVal = "this is a test";
|
|
66
|
+
const myPropsBlob = { name: "MyBlob", namespace: "test1", id: 10 };
|
|
67
|
+
const testRange = new Uint8Array(500);
|
|
68
|
+
testRange.fill(11);
|
|
69
|
+
withEditTxn(iModel, (txn) => {
|
|
70
|
+
txn.saveFileProperty(myPropsStr, myStrVal);
|
|
71
|
+
const readFromDb = iModel.queryFilePropertyString(myPropsStr);
|
|
72
|
+
assert.equal(readFromDb, myStrVal, "query string after save");
|
|
73
|
+
txn.saveFileProperty(myPropsBlob, undefined, testRange);
|
|
74
|
+
const blobFromDb = iModel.queryFilePropertyBlob(myPropsBlob);
|
|
75
|
+
assert.deepEqual(blobFromDb, testRange, "query blob after save");
|
|
76
|
+
let next = iModel.queryNextAvailableFileProperty(myPropsBlob);
|
|
77
|
+
assert.equal(11, next, "queryNextAvailableFileProperty blob");
|
|
78
|
+
next = iModel.queryNextAvailableFileProperty(myPropsStr);
|
|
79
|
+
assert.equal(2, next, "queryNextAvailableFileProperty str");
|
|
80
|
+
txn.deleteFileProperty(myPropsStr);
|
|
81
|
+
assert.isUndefined(iModel.queryFilePropertyString(myPropsStr), "property was deleted");
|
|
82
|
+
next = iModel.queryNextAvailableFileProperty(myPropsStr);
|
|
83
|
+
assert.equal(0, next, "queryNextAvailableFileProperty, should return 0 when none present");
|
|
84
|
+
});
|
|
85
|
+
const testLocal = "TestLocal";
|
|
86
|
+
const testValue = "this is a test";
|
|
87
|
+
const nativeDb = iModel[_nativeDb];
|
|
88
|
+
assert.isUndefined(nativeDb.queryLocalValue(testLocal));
|
|
89
|
+
nativeDb.saveLocalValue(testLocal, testValue);
|
|
90
|
+
assert.equal(nativeDb.queryLocalValue(testLocal), testValue);
|
|
91
|
+
iModel.close();
|
|
92
|
+
});
|
|
93
|
+
it("should be able to open checkpoints for RPC", async () => {
|
|
94
|
+
const changeset = { id: "fakeChangeSetId", index: 10 };
|
|
95
|
+
const iTwinId = "fakeIModelId";
|
|
96
|
+
const iModelId = "fakeIModelId";
|
|
97
|
+
const cloudContainer = { accessToken: "sas" };
|
|
98
|
+
const fakeSnapshotDb = {
|
|
99
|
+
cloudContainer,
|
|
100
|
+
isReadonly: () => true,
|
|
101
|
+
isOpen: () => true,
|
|
102
|
+
getIModelId: () => iModelId,
|
|
103
|
+
getITwinId: () => iTwinId,
|
|
104
|
+
getCurrentChangeset: () => changeset,
|
|
105
|
+
hasUnsavedChanges: () => false,
|
|
106
|
+
schemaSyncEnabled: () => false,
|
|
107
|
+
setIModelDb: () => { },
|
|
108
|
+
closeFile: () => { },
|
|
109
|
+
clearECDbCache: () => { },
|
|
110
|
+
};
|
|
111
|
+
const errorLogStub = sinon.stub(Logger, "logError").callsFake(() => { });
|
|
112
|
+
const infoLogStub = sinon.stub(Logger, "logInfo").callsFake(() => { });
|
|
113
|
+
// Mock iModelHub
|
|
114
|
+
const mockCheckpointV2 = {
|
|
115
|
+
accountName: "testAccount",
|
|
116
|
+
containerId: "imodelblocks-123",
|
|
117
|
+
sasToken: "testSAS",
|
|
118
|
+
dbName: "testDb",
|
|
119
|
+
storageType: "azure?sas=1",
|
|
120
|
+
};
|
|
121
|
+
sinon.stub(IModelHost, _hubAccess).get(() => HubMock);
|
|
122
|
+
sinon.stub(V2CheckpointManager, "attach").callsFake(async () => {
|
|
123
|
+
return { dbName: "fakeDb", container: { accessToken: "sas" } };
|
|
124
|
+
});
|
|
125
|
+
const queryStub = sinon.stub(IModelHost[_hubAccess], "queryV2Checkpoint").callsFake(async () => mockCheckpointV2);
|
|
126
|
+
const openDgnDbStub = sinon.stub(SnapshotDb, "openDgnDb").returns(fakeSnapshotDb);
|
|
127
|
+
sinon.stub(IModelDb.prototype, "initializeIModelDb");
|
|
128
|
+
sinon.stub(IModelDb.prototype, "loadIModelSettings");
|
|
129
|
+
const accessToken = "token";
|
|
130
|
+
const checkpoint = await SnapshotDb.openCheckpointFromRpc({ accessToken, iTwinId, iModelId, changeset });
|
|
131
|
+
expect(openDgnDbStub.calledOnce).to.be.true;
|
|
132
|
+
expect(openDgnDbStub.firstCall.firstArg.path).to.equal("fakeDb");
|
|
133
|
+
const props = checkpoint.getRpcProps();
|
|
134
|
+
assert.equal(props.iModelId, iModelId);
|
|
135
|
+
assert.equal(props.iTwinId, iTwinId);
|
|
136
|
+
assert.equal(props.changeset?.id, changeset.id);
|
|
137
|
+
assert.equal(errorLogStub.callCount, 1);
|
|
138
|
+
assert.include(errorLogStub.args[0][1], "attached with timestamp that expires before");
|
|
139
|
+
errorLogStub.resetHistory();
|
|
140
|
+
expect(cloudContainer.accessToken).equal("sas");
|
|
141
|
+
await checkpoint.refreshContainerForRpc(accessToken);
|
|
142
|
+
expect(cloudContainer.accessToken).equal("testSAS");
|
|
143
|
+
assert.equal(errorLogStub.callCount, 1);
|
|
144
|
+
assert.include(errorLogStub.args[0][1], "attached with timestamp that expires before");
|
|
145
|
+
assert.equal(infoLogStub.callCount, 2);
|
|
146
|
+
assert.include(infoLogStub.args[0][1], "attempting to refresh");
|
|
147
|
+
assert.include(infoLogStub.args[1][1], "refreshed checkpoint");
|
|
148
|
+
errorLogStub.resetHistory();
|
|
149
|
+
queryStub.callsFake(async () => {
|
|
150
|
+
throw new Error("no checkpoint");
|
|
151
|
+
});
|
|
152
|
+
await expect(checkpoint.refreshContainerForRpc(accessToken)).to.eventually.be.rejectedWith("no checkpoint");
|
|
153
|
+
checkpoint.close();
|
|
154
|
+
});
|
|
155
|
+
it("should throw for missing/invalid checkpoint in hub", async () => {
|
|
156
|
+
process.env.CHECKPOINT_CACHE_DIR = "/foo/";
|
|
157
|
+
sinon.stub(IModelHost, _hubAccess).get(() => HubMock);
|
|
158
|
+
sinon.stub(IModelHost[_hubAccess], "queryV2Checkpoint").callsFake(async () => undefined);
|
|
159
|
+
const accessToken = "token";
|
|
160
|
+
const error = await getIModelError(SnapshotDb.openCheckpointFromRpc({ accessToken, iTwinId: Guid.createValue(), iModelId: Guid.createValue(), changeset: IModelTestUtils.generateChangeSetId() }));
|
|
161
|
+
expectIModelError(IModelStatus.NotFound, error);
|
|
162
|
+
});
|
|
163
|
+
it("attempting to re-attach a non-checkpoint snapshot should be a no-op", async () => {
|
|
164
|
+
process.env.CHECKPOINT_CACHE_DIR = "/foo/";
|
|
165
|
+
const accessToken = "token";
|
|
166
|
+
const imodel = await importTestBim(createIModelFromSeed("reattachNonCheckpoint.bim", "test.bim"));
|
|
167
|
+
try {
|
|
168
|
+
await imodel.refreshContainerForRpc(accessToken);
|
|
169
|
+
}
|
|
170
|
+
finally {
|
|
171
|
+
imodel.close();
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
it("Check busyTimeout option", () => {
|
|
175
|
+
const standaloneFile = IModelTestUtils.prepareOutputFile("IModel", "StandaloneReadWrite.bim");
|
|
176
|
+
const tryOpen = (fileName, options) => {
|
|
177
|
+
const start = performance.now();
|
|
178
|
+
let didThrow = false;
|
|
179
|
+
try {
|
|
180
|
+
StandaloneDb.openFile(fileName, OpenMode.ReadWrite, options);
|
|
181
|
+
}
|
|
182
|
+
catch (e) {
|
|
183
|
+
assert.strictEqual(e.errorNumber, DbResult.BE_SQLITE_BUSY, "Expect error 'Db is busy'");
|
|
184
|
+
didThrow = true;
|
|
185
|
+
}
|
|
186
|
+
assert.isTrue(didThrow);
|
|
187
|
+
return performance.now() - start;
|
|
188
|
+
};
|
|
189
|
+
const seconds = (s) => s * 1000;
|
|
190
|
+
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "Standalone" } });
|
|
191
|
+
const txn = new EditTxn(db, "busy timeout test");
|
|
192
|
+
txn.start();
|
|
193
|
+
// lock db so another connection cannot write to it.
|
|
194
|
+
txn.saveFileProperty({ name: "test", namespace: "test" }, "");
|
|
195
|
+
assert.isAtMost(tryOpen(standaloneFile, { busyTimeout: seconds(0) }), seconds(1), "open should fail with busy error instantly");
|
|
196
|
+
assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(1) }), seconds(1), "open should fail with atleast 1 sec delay due to retry");
|
|
197
|
+
assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(2) }), seconds(2), "open should fail with atleast 2 sec delay due to retry");
|
|
198
|
+
assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(3) }), seconds(3), "open should fail with atleast 3 sec delay due to retry");
|
|
199
|
+
txn.end("abandon");
|
|
200
|
+
db.close();
|
|
201
|
+
});
|
|
202
|
+
it("Cache cleared on abandonChanges", () => {
|
|
203
|
+
const standaloneFile = IModelTestUtils.prepareOutputFile("IModel", "StandaloneReadWrite.bim");
|
|
204
|
+
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "Standalone" } });
|
|
205
|
+
const txn = new EditTxn(db, "cache cleared on abandonChanges");
|
|
206
|
+
txn.start();
|
|
207
|
+
const code = Code.createEmpty();
|
|
208
|
+
code.value = "foo";
|
|
209
|
+
const props = {
|
|
210
|
+
classFullName: GenericGraphicalType2d.classFullName,
|
|
211
|
+
model: IModel.dictionaryId,
|
|
212
|
+
code,
|
|
213
|
+
};
|
|
214
|
+
const id = txn.insertElement(props);
|
|
215
|
+
const element1 = db.elements.getElementProps(id);
|
|
216
|
+
txn.end("abandon");
|
|
217
|
+
code.value = "bar";
|
|
218
|
+
const props2 = {
|
|
219
|
+
classFullName: GenericGraphicalType2d.classFullName,
|
|
220
|
+
model: IModel.dictionaryId,
|
|
221
|
+
code,
|
|
222
|
+
};
|
|
223
|
+
const retryTxn = new EditTxn(db, "cache cleared on abandonChanges retry");
|
|
224
|
+
retryTxn.start();
|
|
225
|
+
const id2 = retryTxn.insertElement(props2);
|
|
226
|
+
expect(id2).to.equal(id);
|
|
227
|
+
const element2 = db.elements.getElementProps(id2);
|
|
228
|
+
expect(element2).to.not.equal(element1);
|
|
229
|
+
// Exercise the ECSqlStatement cache directly - nothing in the normal insert/read path above uses it anymore.
|
|
230
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
231
|
+
db.withPreparedStatement("SELECT ECInstanceId FROM BisCore:Element LIMIT 1", () => { });
|
|
232
|
+
// Make sure that the statement caches are not cleared
|
|
233
|
+
expect(db._sqliteStatementCache.size).to.be.greaterThan(0);
|
|
234
|
+
expect(db._statementCache.size).to.be.greaterThan(0);
|
|
235
|
+
retryTxn.end("abandon");
|
|
236
|
+
db.close();
|
|
237
|
+
});
|
|
238
|
+
it("Only instance caches should be cleared with clearCaches instanceCachesOnly parameter", () => {
|
|
239
|
+
const standaloneFile = IModelTestUtils.prepareOutputFile("IModel", "StandaloneReadWrite.bim");
|
|
240
|
+
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "Standalone" } });
|
|
241
|
+
const txn = new EditTxn(db, "clearCaches instanceCachesOnly");
|
|
242
|
+
txn.start();
|
|
243
|
+
const code = Code.createEmpty();
|
|
244
|
+
code.value = "foo";
|
|
245
|
+
const props = {
|
|
246
|
+
classFullName: GenericGraphicalType2d.classFullName,
|
|
247
|
+
model: IModel.dictionaryId,
|
|
248
|
+
code,
|
|
249
|
+
};
|
|
250
|
+
const id = txn.insertElement(props);
|
|
251
|
+
db.elements.getElementProps(id);
|
|
252
|
+
db.models.getModelProps(IModel.dictionaryId);
|
|
253
|
+
// Exercise the ECSqlStatement cache directly - nothing in the normal insert/read path above uses it anymore.
|
|
254
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
255
|
+
db.withPreparedStatement("SELECT ECInstanceId FROM BisCore:Element LIMIT 1", () => { });
|
|
256
|
+
expect(db.elements[_cache].size).to.be.greaterThan(0);
|
|
257
|
+
expect(db.models[_cache].size).to.be.greaterThan(0);
|
|
258
|
+
expect(db.elements[_instanceKeyCache].size).to.be.greaterThan(0);
|
|
259
|
+
expect(db.models[_instanceKeyCache].size).to.be.greaterThan(0);
|
|
260
|
+
db.clearCaches({ instanceCachesOnly: true });
|
|
261
|
+
expect(db.elements[_cache].size).to.equal(0);
|
|
262
|
+
expect(db.models[_cache].size).to.equal(0);
|
|
263
|
+
expect(db.elements[_instanceKeyCache].size).to.equal(0);
|
|
264
|
+
expect(db.models[_instanceKeyCache].size).to.equal(0);
|
|
265
|
+
// Make sure that the statement caches are not cleared
|
|
266
|
+
expect(db._sqliteStatementCache.size).to.be.greaterThan(0);
|
|
267
|
+
expect(db._statementCache.size).to.be.greaterThan(0);
|
|
268
|
+
txn.end("abandon");
|
|
269
|
+
db.close();
|
|
270
|
+
});
|
|
271
|
+
it("inserting a second element with an empty code must not evict the first from the element props cache", () => {
|
|
272
|
+
const standaloneFile = IModelTestUtils.prepareOutputFile("IModel", "EmptyCodeCacheCollision.bim");
|
|
273
|
+
const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: "EmptyCodeCacheCollision" } });
|
|
274
|
+
withEditTxn(db, (txn) => {
|
|
275
|
+
const categoryId = SpatialCategory.insert(txn, IModel.dictionaryId, "TestCategory", new SubCategoryAppearance());
|
|
276
|
+
const modelId = PhysicalModel.insert(txn, IModel.rootSubjectId, "TestModel");
|
|
277
|
+
const emptyCodeProps = {
|
|
278
|
+
classFullName: PhysicalObject.classFullName,
|
|
279
|
+
model: modelId,
|
|
280
|
+
category: categoryId,
|
|
281
|
+
code: Code.createEmpty(),
|
|
282
|
+
};
|
|
283
|
+
// Insert the first element
|
|
284
|
+
const id1 = txn.insertElement({ ...emptyCodeProps });
|
|
285
|
+
db.elements.getElementProps(id1); // populate the element props cache
|
|
286
|
+
const cacheSizeAfterFirstInsertAndRead = db.elements[_cache].size;
|
|
287
|
+
expect(cacheSizeAfterFirstInsertAndRead).to.be.greaterThan(0, "cache should be populated after getElementProps");
|
|
288
|
+
// Insert a second element with the same empty code
|
|
289
|
+
const id2 = txn.insertElement({ ...emptyCodeProps });
|
|
290
|
+
// The first element must still be in the cache.
|
|
291
|
+
const cached1 = db.elements[_cache].get({ id: id1 });
|
|
292
|
+
expect(cached1, "first element should still be in cache after inserting second element with the same empty code").to.not.be.undefined;
|
|
293
|
+
expect(cached1.elProps.id).to.equal(id1);
|
|
294
|
+
expect(Id64.isValidId64(id1)).to.be.true;
|
|
295
|
+
expect(Id64.isValidId64(id2)).to.be.true;
|
|
296
|
+
expect(id1).to.not.equal(id2);
|
|
297
|
+
});
|
|
298
|
+
db.close();
|
|
299
|
+
});
|
|
300
|
+
it("Standalone iModel properties", () => {
|
|
301
|
+
const standaloneRootSubjectName = "Standalone";
|
|
302
|
+
const standaloneFile1 = IModelTestUtils.prepareOutputFile("IModel", "Standalone1.bim");
|
|
303
|
+
const ecefLocation = new EcefLocation({ origin: [1, 2, 3], orientation: { yaw: 0, pitch: 0, roll: 0 } });
|
|
304
|
+
const geographicCoordinateSystem = {
|
|
305
|
+
horizontalCRS: { id: "10TM115-27" },
|
|
306
|
+
};
|
|
307
|
+
let standaloneDb1 = StandaloneDb.createEmpty(standaloneFile1, { rootSubject: { name: standaloneRootSubjectName }, ecefLocation, geographicCoordinateSystem });
|
|
308
|
+
assert.isTrue(standaloneDb1.isStandaloneDb());
|
|
309
|
+
assert.isTrue(standaloneDb1.isStandalone);
|
|
310
|
+
assert.isFalse(standaloneDb1.isReadonly, "Expect standalone iModels to be read-write during create");
|
|
311
|
+
assert.equal(standaloneDb1.getBriefcaseId(), BriefcaseIdValue.Unassigned);
|
|
312
|
+
assert.equal(standaloneDb1.pathName, standaloneFile1);
|
|
313
|
+
assert.equal(standaloneDb1, StandaloneDb.tryFindByKey(standaloneDb1.key), "Should be in the list of open StandaloneDbs");
|
|
314
|
+
assert.equal(standaloneDb1.elements.getRootSubject().code.value, standaloneRootSubjectName);
|
|
315
|
+
assert.isTrue(standaloneDb1.isOpen);
|
|
316
|
+
assert.isTrue(Guid.isV4Guid(standaloneDb1.iModelId));
|
|
317
|
+
assert.equal(standaloneDb1.iTwinId, Guid.empty);
|
|
318
|
+
assert.strictEqual("", standaloneDb1.changeset.id);
|
|
319
|
+
assert.strictEqual(0, standaloneDb1.changeset.index);
|
|
320
|
+
assert.deepEqual(standaloneDb1.ecefLocation?.origin, ecefLocation.origin, "standalone ecefLocation should be set");
|
|
321
|
+
assert.strictEqual(standaloneDb1.geographicCoordinateSystem?.horizontalCRS?.id, "10TM115-27", "standalone coordinate system should be set");
|
|
322
|
+
assert.equal(standaloneDb1.openMode, OpenMode.ReadWrite);
|
|
323
|
+
standaloneDb1.close();
|
|
324
|
+
assert.isFalse(standaloneDb1.isOpen);
|
|
325
|
+
standaloneDb1.close(); // calling `close()` a second time is a no-op
|
|
326
|
+
assert.isUndefined(StandaloneDb.tryFindByKey(standaloneDb1.key));
|
|
327
|
+
standaloneDb1 = StandaloneDb.openFile(standaloneFile1);
|
|
328
|
+
assert.equal(standaloneDb1, StandaloneDb.tryFindByKey(standaloneDb1.key));
|
|
329
|
+
assert.isFalse(standaloneDb1.isReadonly, "By default, StandaloneDbs are opened read/write");
|
|
330
|
+
standaloneDb1.close();
|
|
331
|
+
assert.isUndefined(StandaloneDb.tryFindByKey(standaloneDb1.key));
|
|
332
|
+
});
|
|
333
|
+
it("Snapshot iModel properties", async () => {
|
|
334
|
+
const snapshotRootSubjectName = "Snapshot";
|
|
335
|
+
const snapshotFile1 = IModelTestUtils.prepareOutputFile("IModel", "Snapshot1.bim");
|
|
336
|
+
const snapshotFile2 = IModelTestUtils.prepareOutputFile("IModel", "Snapshot2.bim");
|
|
337
|
+
const snapshotFile3 = IModelTestUtils.prepareOutputFile("IModel", "Snapshot3.bim");
|
|
338
|
+
const imodel = await importTestBim(createIModelFromSeed("test_for_snapshot.bim", "test.bim"));
|
|
339
|
+
const ecefLocation = new EcefLocation({ origin: [1, 2, 3], orientation: { yaw: 0, pitch: 0, roll: 0 } });
|
|
340
|
+
const geographicCoordinateSystem = {
|
|
341
|
+
horizontalCRS: { id: "10TM115-27" },
|
|
342
|
+
};
|
|
343
|
+
let snapshotDb1 = SnapshotDb.createEmpty(snapshotFile1, { rootSubject: { name: snapshotRootSubjectName }, createClassViews: true, ecefLocation, geographicCoordinateSystem });
|
|
344
|
+
let snapshotDb2 = SnapshotDb.createFrom(snapshotDb1, snapshotFile2);
|
|
345
|
+
let snapshotDb3 = SnapshotDb.createFrom(imodel, snapshotFile3, { createClassViews: true });
|
|
346
|
+
assert.isTrue(snapshotDb1.isSnapshotDb());
|
|
347
|
+
assert.isTrue(snapshotDb2.isSnapshotDb());
|
|
348
|
+
assert.isTrue(snapshotDb3.isSnapshotDb());
|
|
349
|
+
assert.isTrue(snapshotDb1.isSnapshot);
|
|
350
|
+
assert.isTrue(snapshotDb2.isSnapshot);
|
|
351
|
+
assert.isTrue(snapshotDb3.isSnapshot);
|
|
352
|
+
assert.isFalse(snapshotDb1.isReadonly, "Expect snapshots to be read-write during create");
|
|
353
|
+
assert.isFalse(snapshotDb2.isReadonly, "Expect snapshots to be read-write during create");
|
|
354
|
+
assert.isFalse(snapshotDb3.isReadonly, "Expect snapshots to be read-write during create");
|
|
355
|
+
assert.equal(snapshotDb1.getBriefcaseId(), BriefcaseIdValue.Unassigned);
|
|
356
|
+
assert.equal(snapshotDb2.getBriefcaseId(), BriefcaseIdValue.Unassigned);
|
|
357
|
+
assert.equal(snapshotDb3.getBriefcaseId(), BriefcaseIdValue.Unassigned);
|
|
358
|
+
assert.equal(imodel.getBriefcaseId(), BriefcaseIdValue.Unassigned);
|
|
359
|
+
assert.equal(snapshotDb1.pathName, snapshotFile1);
|
|
360
|
+
assert.equal(snapshotDb2.pathName, snapshotFile2);
|
|
361
|
+
assert.equal(snapshotDb3.pathName, snapshotFile3);
|
|
362
|
+
assert.equal(snapshotDb1, SnapshotDb.tryFindByKey(snapshotDb1.key));
|
|
363
|
+
assert.equal(snapshotDb2, SnapshotDb.tryFindByKey(snapshotDb2.key));
|
|
364
|
+
assert.equal(snapshotDb3, SnapshotDb.tryFindByKey(snapshotDb3.key));
|
|
365
|
+
const iModelGuid1 = snapshotDb1.iModelId;
|
|
366
|
+
const iModelGuid2 = snapshotDb2.iModelId;
|
|
367
|
+
const iModelGuid3 = snapshotDb3.iModelId;
|
|
368
|
+
assert.notEqual(iModelGuid1, iModelGuid2, "Expect different iModel GUIDs for each snapshot");
|
|
369
|
+
assert.notEqual(iModelGuid2, iModelGuid3, "Expect different iModel GUIDs for each snapshot");
|
|
370
|
+
const rootSubjectName1 = snapshotDb1.elements.getRootSubject().code.value;
|
|
371
|
+
const rootSubjectName2 = snapshotDb2.elements.getRootSubject().code.value;
|
|
372
|
+
const rootSubjectName3 = snapshotDb3.elements.getRootSubject().code.value;
|
|
373
|
+
const imodelRootSubjectName = imodel.elements.getRootSubject().code.value;
|
|
374
|
+
assert.equal(rootSubjectName1, snapshotRootSubjectName);
|
|
375
|
+
assert.equal(rootSubjectName1, rootSubjectName2, "Expect a snapshot to maintain the root Subject name from its seed");
|
|
376
|
+
assert.equal(rootSubjectName3, imodelRootSubjectName, "Expect a snapshot to maintain the root Subject name from its seed");
|
|
377
|
+
assert.isTrue(snapshotDb1.isOpen);
|
|
378
|
+
assert.isTrue(snapshotDb2.isOpen);
|
|
379
|
+
assert.isTrue(snapshotDb3.isOpen);
|
|
380
|
+
assert.deepEqual(snapshotDb1.ecefLocation?.origin, ecefLocation.origin, "snapshot ecefLocation should be set");
|
|
381
|
+
assert.strictEqual(snapshotDb1.geographicCoordinateSystem?.horizontalCRS?.id, "10TM115-27", "snapshot coordinate system should be set");
|
|
382
|
+
snapshotDb1.close();
|
|
383
|
+
snapshotDb2.close();
|
|
384
|
+
snapshotDb3.close();
|
|
385
|
+
assert.isFalse(snapshotDb1.isOpen);
|
|
386
|
+
assert.isFalse(snapshotDb2.isOpen);
|
|
387
|
+
assert.isFalse(snapshotDb3.isOpen);
|
|
388
|
+
snapshotDb1.close(); // calling `close()` a second time is a no-op
|
|
389
|
+
snapshotDb2.close(); // calling `close()` a second time is a no-op
|
|
390
|
+
snapshotDb3.close(); // calling `close()` a second time is a no-op
|
|
391
|
+
assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb1.key));
|
|
392
|
+
assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb2.key));
|
|
393
|
+
assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb3.key));
|
|
394
|
+
snapshotDb1 = SnapshotDb.openFile(snapshotFile1);
|
|
395
|
+
snapshotDb2 = SnapshotDb.openFile(snapshotFile2);
|
|
396
|
+
snapshotDb3 = SnapshotDb.openFile(snapshotFile3);
|
|
397
|
+
assert.equal(snapshotDb1, SnapshotDb.tryFindByKey(snapshotDb1.key));
|
|
398
|
+
assert.equal(snapshotDb2, SnapshotDb.tryFindByKey(snapshotDb2.key));
|
|
399
|
+
assert.equal(snapshotDb3, SnapshotDb.tryFindByKey(snapshotDb3.key));
|
|
400
|
+
assert.equal(snapshotDb3, SnapshotDb.findByKey(snapshotDb3.key));
|
|
401
|
+
assert.equal(snapshotDb3, IModelDb.findByKey(snapshotDb3.key));
|
|
402
|
+
assert.throws(() => BriefcaseDb.findByKey(snapshotDb1.key)); // lookup of key for SnapshotDb via BriefcaseDb should throw
|
|
403
|
+
assert.throws(() => StandaloneDb.findByKey(snapshotDb1.key)); // likewise for StandaloneDb
|
|
404
|
+
assert.isTrue(snapshotDb1.isReadonly, "Expect snapshots to be read-only after open");
|
|
405
|
+
assert.isTrue(snapshotDb2.isReadonly, "Expect snapshots to be read-only after open");
|
|
406
|
+
assert.isTrue(snapshotDb3.isReadonly, "Expect snapshots to be read-only after open");
|
|
407
|
+
assert.isTrue(hasClassView(snapshotDb1, "bis.Element"));
|
|
408
|
+
assert.isTrue(hasClassView(snapshotDb1, "bis.ElementAspect"));
|
|
409
|
+
assert.isTrue(hasClassView(snapshotDb1, "bis.Model"));
|
|
410
|
+
assert.isTrue(hasClassView(snapshotDb1, "bis.ElementRefersToElements"));
|
|
411
|
+
assert.isFalse(hasClassView(snapshotDb2, "bis.Element"));
|
|
412
|
+
assert.isTrue(hasClassView(snapshotDb3, "bis.Element"));
|
|
413
|
+
imodel.close();
|
|
414
|
+
snapshotDb1.close();
|
|
415
|
+
snapshotDb2.close();
|
|
416
|
+
snapshotDb3.close();
|
|
417
|
+
assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb1.key));
|
|
418
|
+
assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb2.key));
|
|
419
|
+
assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb3.key));
|
|
420
|
+
});
|
|
421
|
+
it("upgrade the domain schema in a StandaloneDb", async () => {
|
|
422
|
+
const testFileName = IModelTestUtils.prepareOutputFile("UpgradeIModel", "testImodel.bim");
|
|
423
|
+
const seedFileName = IModelTestUtils.resolveAssetFile("testImodel.bim");
|
|
424
|
+
IModelJsFs.copySync(seedFileName, testFileName);
|
|
425
|
+
let iModel = StandaloneDb.openFile(testFileName, OpenMode.ReadWrite);
|
|
426
|
+
const beforeVersion = iModel.querySchemaVersion("BisCore");
|
|
427
|
+
assert.isTrue(semver.satisfies(beforeVersion, "= 1.0.0"));
|
|
428
|
+
iModel.close();
|
|
429
|
+
const schemaState = StandaloneDb.validateSchemas(testFileName, true);
|
|
430
|
+
assert.strictEqual(schemaState, SchemaState.UpgradeRecommended);
|
|
431
|
+
StandaloneDb.upgradeStandaloneSchemas(testFileName);
|
|
432
|
+
iModel = StandaloneDb.openFile(testFileName, OpenMode.ReadWrite);
|
|
433
|
+
const afterVersion = iModel.querySchemaVersion("BisCore");
|
|
434
|
+
assert.isTrue(semver.satisfies(afterVersion, ">= 1.0.10"));
|
|
435
|
+
iModel.close();
|
|
436
|
+
});
|
|
437
|
+
it("throws NotFound when attempting to access element props after closing the iModel", () => {
|
|
438
|
+
const imodelPath = IModelTestUtils.prepareOutputFile("IModel", "accessAfterClose.bim");
|
|
439
|
+
const imodel = SnapshotDb.createEmpty(imodelPath, { rootSubject: { name: "accessAfterClose" } });
|
|
440
|
+
const elem = imodel.elements.getElement(IModel.rootSubjectId);
|
|
441
|
+
expect(elem.id).to.equal(IModel.rootSubjectId);
|
|
442
|
+
imodel.close();
|
|
443
|
+
expect(() => imodel.elements.getElement(IModel.rootSubjectId)).to.throw(IModelError, "Element=0x1", "Not Found");
|
|
444
|
+
});
|
|
445
|
+
it("should provide meaningful error when querying a closed iModel", () => {
|
|
446
|
+
const testImodel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IModel", "QueryingClosedImodel.bim"), { rootSubject: { name: "QueryClosedTest" } });
|
|
447
|
+
assert.isTrue(testImodel.isOpen);
|
|
448
|
+
// Close the iModel for the tests
|
|
449
|
+
testImodel.close();
|
|
450
|
+
assert.isFalse(testImodel.isOpen);
|
|
451
|
+
const closedDbError = "db not open";
|
|
452
|
+
expect(() => testImodel.withPreparedSqliteStatement("SELECT 1", () => { })).to.throw(closedDbError);
|
|
453
|
+
expect(() => testImodel.withPreparedSqliteStatement("SELECT 1", () => { })).to.throw(closedDbError);
|
|
454
|
+
expect(() => testImodel.prepareSqliteStatement("SELECT 1")).to.throw(closedDbError);
|
|
455
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
456
|
+
expect(() => testImodel.prepareStatement("SELECT 1")).to.throw(closedDbError);
|
|
457
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
458
|
+
expect(() => testImodel.withPreparedStatement("SELECT ECInstanceId FROM BisCore:Element LIMIT 1", () => { })).to.throw(closedDbError);
|
|
459
|
+
expect(() => testImodel.elements.queryChildren(IModel.rootSubjectId)).to.throw(closedDbError);
|
|
460
|
+
expect(() => testImodel.elements.getAspects("0x1", "WrongSchema:WrongClass")).to.throw(closedDbError);
|
|
461
|
+
expect(() => testImodel.createQueryReader("SELECT 1")).to.throw(closedDbError);
|
|
462
|
+
});
|
|
463
|
+
});
|
|
464
|
+
describe("IModelDb.requireMinimumSchemaVersion", () => {
|
|
465
|
+
let imodel;
|
|
466
|
+
before(async () => {
|
|
467
|
+
await TestUtils.startBackend();
|
|
468
|
+
imodel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile("IModel", "MinSchemaVer.bim"), { rootSubject: { name: "MinSchemaVer" } });
|
|
469
|
+
});
|
|
470
|
+
after(() => {
|
|
471
|
+
imodel.close();
|
|
472
|
+
});
|
|
473
|
+
it("throws if the schema does not exist", () => {
|
|
474
|
+
expect(() => imodel.requireMinimumSchemaVersion("FakeSchema", new ECVersion(1, 0, 0), "Scrobbles")).to.throw("Scrobbles requires FakeSchema v01.00.00 or newer");
|
|
475
|
+
});
|
|
476
|
+
it("throws IFF the schema version is older than the minimum", () => {
|
|
477
|
+
function test(minVer, expectError) {
|
|
478
|
+
expect(imodel.meetsMinimumSchemaVersion("BisCore", minVer)).to.equal(!expectError);
|
|
479
|
+
const require = () => imodel.requireMinimumSchemaVersion("BisCore", minVer, "Scrobbles");
|
|
480
|
+
if (expectError) {
|
|
481
|
+
expect(require).to.throw(`Scrobbles requires BisCore v${minVer.toString()} or newer`);
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
require();
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
const bisVer = imodel.querySchemaVersionNumbers("BisCore");
|
|
488
|
+
expect(bisVer.read).to.equal(1);
|
|
489
|
+
expect(bisVer.write).to.equal(0);
|
|
490
|
+
expect(bisVer.minor).to.least(24);
|
|
491
|
+
test(bisVer, false);
|
|
492
|
+
test(new ECVersion(bisVer.read, bisVer.write, bisVer.minor - 1), false);
|
|
493
|
+
test(new ECVersion(0, 0, 1), false);
|
|
494
|
+
test(new ECVersion(bisVer.read, bisVer.write, bisVer.minor + 1), true);
|
|
495
|
+
test(new ECVersion(bisVer.read, bisVer.write, bisVer.minor + 1), true);
|
|
496
|
+
test(new ECVersion(bisVer.read + 1, bisVer.write + 1, bisVer.minor), true);
|
|
497
|
+
});
|
|
498
|
+
});
|
|
499
|
+
//# sourceMappingURL=IModelLifecycle.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IModelLifecycle.test.js","sourceRoot":"","sources":["../../../../src/test/imodel/IModelLifecycle.test.ts"],"names":[],"mappings":"AAAA;;;+FAG+F;AAC/F,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AACtC,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAc,IAAI,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACvG,OAAO,EAAE,gBAAgB,EAAwB,IAAI,EAAE,YAAY,EAA4C,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,qBAAqB,EAA8B,MAAM,oBAAoB,CAAC;AAC/N,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAErD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EAAE,sBAAsB,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,YAAY,EAAW,MAAM,oBAAoB,CAAC;AACjL,OAAO,EAAE,WAAW,EAAsB,MAAM,gBAAgB,CAAC;AACjE,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAG9G,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,WAA8B,CAAC;IAEnC,MAAM,CAAC,KAAK,IAAI,EAAE;QAChB,WAAW,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACjC,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;QAC/B,eAAe,CAAC,qBAAqB,EAAE,CAAC;IAC1C,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,EAAE;QACT,OAAO,CAAC,GAAG,GAAG,WAAW,CAAC;IAC5B,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,KAAK,CAAC,OAAO,EAAE,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,SAAS,YAAY,CAAC,EAAY,EAAE,IAAY;QAC9C,IAAI,CAAC;YACH,OAAO,EAAE,CAAC,mBAAmB,CAAC,6BAA6B,IAAI,GAAG,EAAE,GAAY,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAClG,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,IAAI,GAAG;YACX,WAAW,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,WAAW,EAAE,YAAY,EAAE;YAC/D,MAAM,EAAE,iBAAiB;YACzB,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,EAAE;YAC9B,cAAc,EAAE,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE;YACvF,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE;SACzB,CAAC;QAEF,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,IAAI,CAAC,CAAC;QAC7G,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC7D,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;QAC3E,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAEvC,MAAM,MAAM,GAAG,MAAM,CAAC,uBAAuB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAC;QACvF,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;QAE3D,MAAM,MAAM,GAAG,MAAM,CAAC,qBAAqB,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,CAAC,CAAC;QACpF,MAAM,CAAC,KAAK,CAAC,MAAO,CAAC,UAAU,EAAE,EAAE,EAAE,qBAAqB,CAAC,CAAC;QAE5D,MAAM,UAAU,GAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;QAC9F,MAAM,QAAQ,GAAG,gBAAgB,CAAC;QAClC,MAAM,WAAW,GAAsB,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC;QACtF,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;QACtC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnB,WAAW,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,GAAG,CAAC,gBAAgB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YAC3C,MAAM,UAAU,GAAG,MAAM,CAAC,uBAAuB,CAAC,UAAU,CAAC,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,EAAE,yBAAyB,CAAC,CAAC;YAE9D,GAAG,CAAC,gBAAgB,CAAC,WAAW,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;YACxD,MAAM,UAAU,GAAG,MAAM,CAAC,qBAAqB,CAAC,WAAW,CAAC,CAAC;YAC7D,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,SAAS,EAAE,uBAAuB,CAAC,CAAC;YAEjE,IAAI,IAAI,GAAG,MAAM,CAAC,8BAA8B,CAAC,WAAW,CAAC,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,IAAI,EAAE,qCAAqC,CAAC,CAAC;YAE9D,IAAI,GAAG,MAAM,CAAC,8BAA8B,CAAC,UAAU,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,oCAAoC,CAAC,CAAC;YAC5D,GAAG,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;YACnC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,uBAAuB,CAAC,UAAU,CAAC,EAAE,sBAAsB,CAAC,CAAC;YACvF,IAAI,GAAG,MAAM,CAAC,8BAA8B,CAAC,UAAU,CAAC,CAAC;YACzD,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,mEAAmE,CAAC,CAAC;QAC7F,CAAC,CAAC,CAAC;QAEH,MAAM,SAAS,GAAG,WAAW,CAAC;QAC9B,MAAM,SAAS,GAAG,gBAAgB,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;QACnC,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC,CAAC;QACxD,QAAQ,CAAC,cAAc,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAC9C,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC;QAE7D,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,SAAS,GAAyB,EAAE,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC7E,MAAM,OAAO,GAAG,cAAc,CAAC;QAC/B,MAAM,QAAQ,GAAG,cAAc,CAAC;QAChC,MAAM,cAAc,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,CAAC;QAC9C,MAAM,cAAc,GACpB;YACE,cAAc;YACd,UAAU,EAAE,GAAG,EAAE,CAAC,IAAI;YACtB,MAAM,EAAE,GAAG,EAAE,CAAC,IAAI;YAClB,WAAW,EAAE,GAAG,EAAE,CAAC,QAAQ;YAC3B,UAAU,EAAE,GAAG,EAAE,CAAC,OAAO;YACzB,mBAAmB,EAAE,GAAG,EAAE,CAAC,SAAS;YACpC,iBAAiB,EAAE,GAAG,EAAE,CAAC,KAAK;YAC9B,iBAAiB,EAAE,GAAG,EAAE,CAAC,KAAK;YAC9B,WAAW,EAAE,GAAG,EAAE,GAAG,CAAC;YACtB,SAAS,EAAE,GAAG,EAAE,GAAG,CAAC;YACpB,cAAc,EAAE,GAAG,EAAE,GAAG,CAAC;SAC1B,CAAC;QAEF,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QACzE,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAEvE,iBAAiB;QACjB,MAAM,gBAAgB,GAA4B;YAChD,WAAW,EAAE,aAAa;YAC1B,WAAW,EAAE,kBAAkB;YAC/B,QAAQ,EAAE,SAAS;YACnB,MAAM,EAAE,QAAQ;YAChB,WAAW,EAAE,aAAa;SAC3B,CAAC;QAEF,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YAC7D,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,WAAW,EAAE,KAAK,EAAS,EAAE,CAAC;QACxE,CAAC,CAAC,CAAC;QACH,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,gBAAgB,CAAC,CAAC;QAElH,MAAM,aAAa,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,oBAA2B,CAAC,CAAC;QAC5D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,EAAE,oBAA2B,CAAC,CAAC;QAE5D,MAAM,WAAW,GAAG,OAAO,CAAC;QAC5B,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,qBAAqB,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACzG,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;QAC5C,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAEjE,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACvC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACrC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,6CAA6C,CAAC,CAAC;QAEvF,YAAY,CAAC,YAAY,EAAE,CAAC;QAC5B,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,UAAU,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAEpD,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,6CAA6C,CAAC,CAAC;QACvF,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACvC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,uBAAuB,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAE/D,YAAY,CAAC,YAAY,EAAE,CAAC;QAC5B,SAAS,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE;YAC7B,MAAM,IAAI,KAAK,CAAC,eAAe,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,UAAU,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,YAAY,CAAC,eAAe,CAAC,CAAC;QAE5G,UAAU,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;QAClE,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,OAAO,CAAC;QAC3C,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC;QACtD,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,mBAAmB,CAAC,CAAC,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,SAAS,CAAC,CAAC;QAEzF,MAAM,WAAW,GAAG,OAAO,CAAC;QAC5B,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,UAAU,CAAC,qBAAqB,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,eAAe,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC,CAAC;QACnM,iBAAiB,CAAC,YAAY,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,OAAO,CAAC,GAAG,CAAC,oBAAoB,GAAG,OAAO,CAAC;QAC3C,MAAM,WAAW,GAAG,OAAO,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,oBAAoB,CAAC,2BAA2B,EAAE,UAAU,CAAC,CAAC,CAAC;QAClG,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;QACnD,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,CAAC;IACH,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,cAAc,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;QAC9F,MAAM,OAAO,GAAG,CAAC,QAAgB,EAAE,OAA4B,EAAE,EAAE;YACjE,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAChC,IAAI,QAAQ,GAAG,KAAK,CAAC;YACrB,IAAI,CAAC;gBACH,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;YAC/D,CAAC;YAAC,OAAO,CAAM,EAAE,CAAC;gBAChB,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,cAAc,EAAE,2BAA2B,CAAC,CAAC;gBACxF,QAAQ,GAAG,IAAI,CAAC;YAClB,CAAC;YACD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACxB,OAAO,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACnC,CAAC,CAAC;QACF,MAAM,OAAO,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC;QAExC,MAAM,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QAC7F,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,EAAE,mBAAmB,CAAC,CAAC;QACjD,GAAG,CAAC,KAAK,EAAE,CAAC;QACZ,oDAAoD;QACpD,GAAG,CAAC,gBAAgB,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QAE9D,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,4CAA4C,CAAC,CAAC;QAChI,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,wDAAwD,CAAC,CAAC;QAC7I,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,wDAAwD,CAAC,CAAC;QAC7I,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,wDAAwD,CAAC,CAAC;QAE7I,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnB,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,cAAc,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;QAC9F,MAAM,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QAC7F,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,EAAE,iCAAiC,CAAC,CAAC;QAC/D,GAAG,CAAC,KAAK,EAAE,CAAC;QAEZ,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,KAAK,GAA+B;YACxC,aAAa,EAAE,sBAAsB,CAAC,aAAa;YACnD,KAAK,EAAE,MAAM,CAAC,YAAY;YAC1B,IAAI;SACL,CAAC;QACF,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QACjD,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEnB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,MAAM,GAA+B;YACzC,aAAa,EAAE,sBAAsB,CAAC,aAAa;YACnD,KAAK,EAAE,MAAM,CAAC,YAAY;YAC1B,IAAI;SACL,CAAC;QACF,MAAM,QAAQ,GAAG,IAAI,OAAO,CAAC,EAAE,EAAE,uCAAuC,CAAC,CAAC;QAC1E,QAAQ,CAAC,KAAK,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACzB,MAAM,QAAQ,GAAG,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAExC,6GAA6G;QAC7G,4DAA4D;QAC5D,EAAE,CAAC,qBAAqB,CAAC,kDAAkD,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAExF,sDAAsD;QACtD,MAAM,CAAE,EAAU,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,CAAE,EAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE9D,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACxB,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,sFAAsF,EAAE,GAAG,EAAE;QAC9F,MAAM,cAAc,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,yBAAyB,CAAC,CAAC;QAC9F,MAAM,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QAC7F,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,EAAE,EAAE,gCAAgC,CAAC,CAAC;QAC9D,GAAG,CAAC,KAAK,EAAE,CAAC;QAEZ,MAAM,IAAI,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,MAAM,KAAK,GAA+B;YACxC,aAAa,EAAE,sBAAsB,CAAC,aAAa;YACnD,KAAK,EAAE,MAAM,CAAC,YAAY;YAC1B,IAAI;SACL,CAAC;QACF,MAAM,EAAE,GAAG,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QACpC,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;QAChC,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC;QAC7C,6GAA6G;QAC7G,4DAA4D;QAC5D,EAAE,CAAC,qBAAqB,CAAC,kDAAkD,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAExF,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE/D,EAAE,CAAC,WAAW,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC;QAE7C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7C,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3C,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtD,sDAAsD;QACtD,MAAM,CAAE,EAAU,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACpE,MAAM,CAAE,EAAU,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE9D,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACnB,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,qGAAqG,EAAE,GAAG,EAAE;QAC7G,MAAM,cAAc,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,6BAA6B,CAAC,CAAC;QAClG,MAAM,EAAE,GAAG,YAAY,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,EAAE,CAAC,CAAC;QAE1G,WAAW,CAAC,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;YACtB,MAAM,UAAU,GAAG,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,YAAY,EAAE,cAAc,EAAE,IAAI,qBAAqB,EAAE,CAAC,CAAC;YACjH,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;YAE7E,MAAM,cAAc,GAA0B;gBAC5C,aAAa,EAAE,cAAc,CAAC,aAAa;gBAC3C,KAAK,EAAE,OAAO;gBACd,QAAQ,EAAE,UAAU;gBACpB,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE;aACzB,CAAC;YAEF,2BAA2B;YAC3B,MAAM,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC;YACrD,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,mCAAmC;YACrE,MAAM,gCAAgC,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC;YAClE,MAAM,CAAC,gCAAgC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,iDAAiD,CAAC,CAAC;YAEjH,mDAAmD;YACnD,MAAM,GAAG,GAAG,GAAG,CAAC,aAAa,CAAC,EAAE,GAAG,cAAc,EAAE,CAAC,CAAC;YAErD,gDAAgD;YAChD,MAAM,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM,CAAC,OAAO,EAAE,gGAAgG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC;YACtI,MAAM,CAAC,OAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAE1C,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YACzC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;YACzC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACtC,MAAM,yBAAyB,GAAG,YAAY,CAAC;QAC/C,MAAM,eAAe,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CAAC;QACvF,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACzG,MAAM,0BAA0B,GAAG;YACjC,aAAa,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE;SACpC,CAAC;QACF,IAAI,aAAa,GAAG,YAAY,CAAC,WAAW,CAAC,eAAe,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,yBAAyB,EAAE,EAAE,YAAY,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC9J,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC,CAAC;QAC9C,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,EAAE,0DAA0D,CAAC,CAAC;QACrG,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,cAAc,EAAE,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QAC1E,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,6CAA6C,CAAC,CAAC;QACzH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,yBAAyB,CAAC,CAAC;QAC5F,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,CAAC;QACrD,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAChD,MAAM,CAAC,WAAW,CAAC,EAAE,EAAE,aAAa,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACrD,MAAM,CAAC,SAAS,CAAC,aAAa,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,uCAAuC,CAAC,CAAC;QACnH,MAAM,CAAC,WAAW,CAAC,aAAa,CAAC,0BAA0B,EAAE,aAAa,EAAE,EAAE,EAAE,YAAY,EAAE,4CAA4C,CAAC,CAAC;QAC5I,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;QACzD,aAAa,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACrC,aAAa,CAAC,KAAK,EAAE,CAAC,CAAC,6CAA6C;QACpE,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QACjE,aAAa,GAAG,YAAY,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACvD,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,YAAY,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1E,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;QAC5F,aAAa,CAAC,KAAK,EAAE,CAAC;QACtB,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;QAC1C,MAAM,uBAAuB,GAAG,UAAU,CAAC;QAC3C,MAAM,aAAa,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QACnF,MAAM,aAAa,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QACnF,MAAM,aAAa,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;QACnF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC,oBAAoB,CAAC,uBAAuB,EAAE,UAAU,CAAC,CAAC,CAAC;QAC9F,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACzG,MAAM,0BAA0B,GAAG;YACjC,aAAa,EAAE,EAAE,EAAE,EAAE,YAAY,EAAE;SACpC,CAAC;QACF,IAAI,WAAW,GAAG,UAAU,CAAC,WAAW,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,EAAE,0BAA0B,EAAE,CAAC,CAAC;QAC9K,IAAI,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;QACpE,IAAI,WAAW,GAAG,UAAU,CAAC,UAAU,CAAC,MAAM,EAAE,aAAa,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC,CAAC;QAC1C,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;QACtC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;QAC1F,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;QAC1F,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;QAC1F,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,cAAc,EAAE,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACxE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,gBAAgB,CAAC,UAAU,CAAC,CAAC;QACnE,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClD,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,WAAW,GAAe,WAAW,CAAC,QAAQ,CAAC;QACrD,MAAM,WAAW,GAAe,WAAW,CAAC,QAAQ,CAAC;QACrD,MAAM,WAAW,GAAe,WAAW,CAAC,QAAQ,CAAC;QACrD,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,iDAAiD,CAAC,CAAC;QAC7F,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,iDAAiD,CAAC,CAAC;QAC7F,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1E,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1E,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1E,MAAM,qBAAqB,GAAG,MAAM,CAAC,QAAQ,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;QAC1E,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,uBAAuB,CAAC,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,gBAAgB,EAAE,mEAAmE,CAAC,CAAC;QACtH,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,qBAAqB,EAAE,mEAAmE,CAAC,CAAC;QAC3H,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,EAAE,qCAAqC,CAAC,CAAC;QAC/G,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,0BAA0B,EAAE,aAAa,EAAE,EAAE,EAAE,YAAY,EAAE,0CAA0C,CAAC,CAAC;QACxI,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QACnC,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,6CAA6C;QAClE,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,6CAA6C;QAClE,WAAW,CAAC,KAAK,EAAE,CAAC,CAAC,6CAA6C;QAClE,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACjD,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACjD,WAAW,GAAG,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACjD,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,UAAU,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,QAAQ,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,4DAA4D;QACzH,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,4BAA4B;QAC1F,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,6CAA6C,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,6CAA6C,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,UAAU,EAAE,6CAA6C,CAAC,CAAC;QACrF,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAC,CAAC;QAC9D,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;QACtD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,6BAA6B,CAAC,CAAC,CAAC;QACxE,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC,CAAC;QAExD,MAAM,CAAC,KAAK,EAAE,CAAC;QACf,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,CAAC,KAAK,EAAE,CAAC;QACpB,WAAW,CAAC,KAAK,EAAE,CAAC;QAEpB,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;QAC7D,MAAM,CAAC,WAAW,CAAC,UAAU,CAAC,YAAY,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,MAAM,YAAY,GAAG,eAAe,CAAC,iBAAiB,CAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;QAC1F,MAAM,YAAY,GAAG,eAAe,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;QACxE,UAAU,CAAC,QAAQ,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAEhD,IAAI,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;QACrE,MAAM,aAAa,GAAG,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,aAAc,EAAE,SAAS,CAAC,CAAC,CAAC;QAC3D,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,MAAM,WAAW,GAAgB,YAAY,CAAC,eAAe,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;QAClF,MAAM,CAAC,WAAW,CAAC,WAAW,EAAE,WAAW,CAAC,kBAAkB,CAAC,CAAC;QAEhE,YAAY,CAAC,wBAAwB,CAAC,YAAY,CAAC,CAAC;QAEpD,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC;QACjE,MAAM,YAAY,GAAG,MAAM,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,YAAa,EAAE,WAAW,CAAC,CAAC,CAAC;QAC5D,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,kFAAkF,EAAE,GAAG,EAAE;QAC1F,MAAM,UAAU,GAAG,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;QACvF,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE,EAAE,CAAC,CAAC;QAEjG,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAU,MAAM,CAAC,aAAa,CAAC,CAAC;QACvE,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC;QAE/C,MAAM,CAAC,KAAK,EAAE,CAAC;QAEf,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAU,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;IAC5H,CAAC,CAAC,CAAC;IACH,EAAE,CAAC,+DAA+D,EAAE,GAAG,EAAE;QACvE,MAAM,UAAU,GAAG,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,0BAA0B,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACjK,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAEjC,iCAAiC;QACjC,UAAU,CAAC,KAAK,EAAE,CAAC;QACnB,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QAElC,MAAM,aAAa,GAAG,aAAa,CAAC;QACpC,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,2BAA2B,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACpG,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,2BAA2B,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACpG,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,sBAAsB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACpF,4DAA4D;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9E,4DAA4D;QAC5D,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,qBAAqB,CAAC,kDAAkD,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACtI,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QAC9F,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,EAAE,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACtG,MAAM,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;IACjF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACpD,IAAI,MAAkB,CAAC;IAEvB,MAAM,CAAC,KAAK,IAAI,EAAE;QAChB,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC;QAC/B,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,eAAe,CAAC,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC;IAC9I,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,GAAG,EAAE;QACT,MAAM,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC7C,MAAM,CACJ,GAAG,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,YAAY,EAAE,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,WAAW,CAAC,CAC5F,CAAC,EAAE,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yDAAyD,EAAE,GAAG,EAAE;QACjE,SAAS,IAAI,CAAC,MAAiB,EAAE,WAAoB;YACnD,MAAM,CAAC,MAAM,CAAC,yBAAyB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,CAAC;YACnF,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;YACzF,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,+BAA+B,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;YACxF,CAAC;iBAAM,CAAC;gBACN,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,CAAC,yBAAyB,CAAC,SAAS,CAAE,CAAC;QAC5D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACjC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAElC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACpB,IAAI,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxE,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QAEpC,IAAI,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC;IAC7E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\nimport { assert, expect } from \"chai\";\r\nimport * as semver from \"semver\";\r\nimport * as sinon from \"sinon\";\r\nimport { DbResult, Guid, GuidString, Id64, IModelStatus, Logger, OpenMode } from \"@itwin/core-bentley\";\r\nimport { BriefcaseIdValue, ChangesetIdWithIndex, Code, EcefLocation, FilePropertyProps, GeometricElementProps, IModel, IModelError, SchemaState, SubCategoryAppearance, TypeDefinitionElementProps } from \"@itwin/core-common\";\r\nimport { ECVersion } from \"@itwin/ecschema-metadata\";\r\nimport { V2CheckpointAccessProps } from \"../../BackendHubAccess\";\r\nimport { V2CheckpointManager } from \"../../CheckpointManager\";\r\nimport { EditTxn, withEditTxn } from \"../../EditTxn\";\r\nimport { GenericGraphicalType2d, IModelDb, IModelHost, IModelJsFs, PhysicalModel, PhysicalObject, SnapshotDb, SpatialCategory, StandaloneDb, Subject } from \"../../core-backend\";\r\nimport { BriefcaseDb, SnapshotDbOpenArgs } from \"../../IModelDb\";\r\nimport { HubMock } from \"../../internal/HubMock\";\r\nimport { _cache, _hubAccess, _instanceKeyCache, _nativeDb } from \"../../internal/Symbols\";\r\nimport { IModelTestUtils } from \"../IModelTestUtils\";\r\nimport { TestUtils } from \"../TestUtils\";\r\nimport { performance } from \"perf_hooks\";\r\nimport { createIModelFromSeed, expectIModelError, getIModelError, importTestBim } from \"./IModelTestFixtures\";\r\n\r\n\r\ndescribe(\"iModel lifecycle\", () => {\r\n let originalEnv: NodeJS.ProcessEnv;\r\n\r\n before(async () => {\r\n originalEnv = { ...process.env };\r\n await TestUtils.startBackend();\r\n IModelTestUtils.registerTestBimSchema();\r\n });\r\n\r\n after(() => {\r\n process.env = originalEnv;\r\n });\r\n\r\n afterEach(() => {\r\n sinon.restore();\r\n });\r\n\r\n function hasClassView(db: IModelDb, name: string): boolean {\r\n try {\r\n return db.withSqliteStatement(`SELECT ECInstanceId FROM [${name}]`, (): boolean => true, false);\r\n } catch {\r\n return false;\r\n }\r\n }\r\n\r\n it(\"should be able to create a snapshot IModel\", async () => {\r\n const args = {\r\n rootSubject: { name: \"TestSubject\", description: \"test iTwin\" },\r\n client: \"ABC Engineering\",\r\n globalOrigin: { x: 10, y: 10 },\r\n projectExtents: { low: { x: -300, y: -300, z: -20 }, high: { x: 500, y: 500, z: 400 } },\r\n guid: Guid.createValue(),\r\n };\r\n\r\n const iModel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile(\"IModel\", \"TestSnapshot.bim\"), args);\r\n assert.equal(iModel.iModelId, args.guid);\r\n assert.equal(iModel.rootSubject.name, args.rootSubject.name);\r\n assert.equal(iModel.rootSubject.description, args.rootSubject.description);\r\n assert.equal(iModel.projectExtents.low.x, args.projectExtents.low.x);\r\n assert.equal(iModel.projectExtents.low.y, args.projectExtents.low.y);\r\n assert.equal(iModel.projectExtents.low.z, args.projectExtents.low.z);\r\n assert.equal(iModel.globalOrigin.x, args.globalOrigin.x);\r\n assert.equal(iModel.globalOrigin.y, args.globalOrigin.y);\r\n assert.equal(iModel.globalOrigin.z, 0);\r\n\r\n const client = iModel.queryFilePropertyString({ name: \"Client\", namespace: \"dgn_Db\" });\r\n assert.equal(client, args.client, \"query Client property\");\r\n\r\n const dbguid = iModel.queryFilePropertyBlob({ name: \"DbGuid\", namespace: \"be_Db\" });\r\n assert.equal(dbguid!.byteLength, 16, \"query guid property\");\r\n\r\n const myPropsStr: FilePropertyProps = { name: \"MyProp\", namespace: \"test1\", id: 1, subId: 1 };\r\n const myStrVal = \"this is a test\";\r\n const myPropsBlob: FilePropertyProps = { name: \"MyBlob\", namespace: \"test1\", id: 10 };\r\n const testRange = new Uint8Array(500);\r\n testRange.fill(11);\r\n withEditTxn(iModel, (txn) => {\r\n txn.saveFileProperty(myPropsStr, myStrVal);\r\n const readFromDb = iModel.queryFilePropertyString(myPropsStr);\r\n assert.equal(readFromDb, myStrVal, \"query string after save\");\r\n\r\n txn.saveFileProperty(myPropsBlob, undefined, testRange);\r\n const blobFromDb = iModel.queryFilePropertyBlob(myPropsBlob);\r\n assert.deepEqual(blobFromDb, testRange, \"query blob after save\");\r\n\r\n let next = iModel.queryNextAvailableFileProperty(myPropsBlob);\r\n assert.equal(11, next, \"queryNextAvailableFileProperty blob\");\r\n\r\n next = iModel.queryNextAvailableFileProperty(myPropsStr);\r\n assert.equal(2, next, \"queryNextAvailableFileProperty str\");\r\n txn.deleteFileProperty(myPropsStr);\r\n assert.isUndefined(iModel.queryFilePropertyString(myPropsStr), \"property was deleted\");\r\n next = iModel.queryNextAvailableFileProperty(myPropsStr);\r\n assert.equal(0, next, \"queryNextAvailableFileProperty, should return 0 when none present\");\r\n });\r\n\r\n const testLocal = \"TestLocal\";\r\n const testValue = \"this is a test\";\r\n const nativeDb = iModel[_nativeDb];\r\n assert.isUndefined(nativeDb.queryLocalValue(testLocal));\r\n nativeDb.saveLocalValue(testLocal, testValue);\r\n assert.equal(nativeDb.queryLocalValue(testLocal), testValue);\r\n\r\n iModel.close();\r\n });\r\n it(\"should be able to open checkpoints for RPC\", async () => {\r\n const changeset: ChangesetIdWithIndex = { id: \"fakeChangeSetId\", index: 10 };\r\n const iTwinId = \"fakeIModelId\";\r\n const iModelId = \"fakeIModelId\";\r\n const cloudContainer = { accessToken: \"sas\" };\r\n const fakeSnapshotDb: any =\r\n {\r\n cloudContainer,\r\n isReadonly: () => true,\r\n isOpen: () => true,\r\n getIModelId: () => iModelId,\r\n getITwinId: () => iTwinId,\r\n getCurrentChangeset: () => changeset,\r\n hasUnsavedChanges: () => false,\r\n schemaSyncEnabled: () => false,\r\n setIModelDb: () => { },\r\n closeFile: () => { },\r\n clearECDbCache: () => { },\r\n };\r\n\r\n const errorLogStub = sinon.stub(Logger, \"logError\").callsFake(() => { });\r\n const infoLogStub = sinon.stub(Logger, \"logInfo\").callsFake(() => { });\r\n\r\n // Mock iModelHub\r\n const mockCheckpointV2: V2CheckpointAccessProps = {\r\n accountName: \"testAccount\",\r\n containerId: \"imodelblocks-123\",\r\n sasToken: \"testSAS\",\r\n dbName: \"testDb\",\r\n storageType: \"azure?sas=1\",\r\n };\r\n\r\n sinon.stub(IModelHost, _hubAccess).get(() => HubMock);\r\n sinon.stub(V2CheckpointManager, \"attach\").callsFake(async () => {\r\n return { dbName: \"fakeDb\", container: { accessToken: \"sas\" } as any };\r\n });\r\n const queryStub = sinon.stub(IModelHost[_hubAccess], \"queryV2Checkpoint\").callsFake(async () => mockCheckpointV2);\r\n\r\n const openDgnDbStub = sinon.stub(SnapshotDb, \"openDgnDb\").returns(fakeSnapshotDb);\r\n sinon.stub(IModelDb.prototype, \"initializeIModelDb\" as any);\r\n sinon.stub(IModelDb.prototype, \"loadIModelSettings\" as any);\r\n\r\n const accessToken = \"token\";\r\n const checkpoint = await SnapshotDb.openCheckpointFromRpc({ accessToken, iTwinId, iModelId, changeset });\r\n expect(openDgnDbStub.calledOnce).to.be.true;\r\n expect(openDgnDbStub.firstCall.firstArg.path).to.equal(\"fakeDb\");\r\n\r\n const props = checkpoint.getRpcProps();\r\n assert.equal(props.iModelId, iModelId);\r\n assert.equal(props.iTwinId, iTwinId);\r\n assert.equal(props.changeset?.id, changeset.id);\r\n assert.equal(errorLogStub.callCount, 1);\r\n assert.include(errorLogStub.args[0][1], \"attached with timestamp that expires before\");\r\n\r\n errorLogStub.resetHistory();\r\n expect(cloudContainer.accessToken).equal(\"sas\");\r\n await checkpoint.refreshContainerForRpc(accessToken);\r\n expect(cloudContainer.accessToken).equal(\"testSAS\");\r\n\r\n assert.equal(errorLogStub.callCount, 1);\r\n assert.include(errorLogStub.args[0][1], \"attached with timestamp that expires before\");\r\n assert.equal(infoLogStub.callCount, 2);\r\n assert.include(infoLogStub.args[0][1], \"attempting to refresh\");\r\n assert.include(infoLogStub.args[1][1], \"refreshed checkpoint\");\r\n\r\n errorLogStub.resetHistory();\r\n queryStub.callsFake(async () => {\r\n throw new Error(\"no checkpoint\");\r\n });\r\n await expect(checkpoint.refreshContainerForRpc(accessToken)).to.eventually.be.rejectedWith(\"no checkpoint\");\r\n\r\n checkpoint.close();\r\n });\r\n it(\"should throw for missing/invalid checkpoint in hub\", async () => {\r\n process.env.CHECKPOINT_CACHE_DIR = \"/foo/\";\r\n sinon.stub(IModelHost, _hubAccess).get(() => HubMock);\r\n sinon.stub(IModelHost[_hubAccess], \"queryV2Checkpoint\").callsFake(async () => undefined);\r\n\r\n const accessToken = \"token\";\r\n const error = await getIModelError(SnapshotDb.openCheckpointFromRpc({ accessToken, iTwinId: Guid.createValue(), iModelId: Guid.createValue(), changeset: IModelTestUtils.generateChangeSetId() }));\r\n expectIModelError(IModelStatus.NotFound, error);\r\n });\r\n it(\"attempting to re-attach a non-checkpoint snapshot should be a no-op\", async () => {\r\n process.env.CHECKPOINT_CACHE_DIR = \"/foo/\";\r\n const accessToken = \"token\";\r\n const imodel = await importTestBim(createIModelFromSeed(\"reattachNonCheckpoint.bim\", \"test.bim\"));\r\n try {\r\n await imodel.refreshContainerForRpc(accessToken);\r\n } finally {\r\n imodel.close();\r\n }\r\n });\r\n it(\"Check busyTimeout option\", () => {\r\n const standaloneFile = IModelTestUtils.prepareOutputFile(\"IModel\", \"StandaloneReadWrite.bim\");\r\n const tryOpen = (fileName: string, options?: SnapshotDbOpenArgs) => {\r\n const start = performance.now();\r\n let didThrow = false;\r\n try {\r\n StandaloneDb.openFile(fileName, OpenMode.ReadWrite, options);\r\n } catch (e: any) {\r\n assert.strictEqual(e.errorNumber, DbResult.BE_SQLITE_BUSY, \"Expect error 'Db is busy'\");\r\n didThrow = true;\r\n }\r\n assert.isTrue(didThrow);\r\n return performance.now() - start;\r\n };\r\n const seconds = (s: number) => s * 1000;\r\n\r\n const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: \"Standalone\" } });\r\n const txn = new EditTxn(db, \"busy timeout test\");\r\n txn.start();\r\n // lock db so another connection cannot write to it.\r\n txn.saveFileProperty({ name: \"test\", namespace: \"test\" }, \"\");\r\n\r\n assert.isAtMost(tryOpen(standaloneFile, { busyTimeout: seconds(0) }), seconds(1), \"open should fail with busy error instantly\");\r\n assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(1) }), seconds(1), \"open should fail with atleast 1 sec delay due to retry\");\r\n assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(2) }), seconds(2), \"open should fail with atleast 2 sec delay due to retry\");\r\n assert.isAtLeast(tryOpen(standaloneFile, { busyTimeout: seconds(3) }), seconds(3), \"open should fail with atleast 3 sec delay due to retry\");\r\n\r\n txn.end(\"abandon\");\r\n db.close();\r\n });\r\n it(\"Cache cleared on abandonChanges\", () => {\r\n const standaloneFile = IModelTestUtils.prepareOutputFile(\"IModel\", \"StandaloneReadWrite.bim\");\r\n const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: \"Standalone\" } });\r\n const txn = new EditTxn(db, \"cache cleared on abandonChanges\");\r\n txn.start();\r\n\r\n const code = Code.createEmpty();\r\n code.value = \"foo\";\r\n const props: TypeDefinitionElementProps = {\r\n classFullName: GenericGraphicalType2d.classFullName,\r\n model: IModel.dictionaryId,\r\n code,\r\n };\r\n const id = txn.insertElement(props);\r\n const element1 = db.elements.getElementProps(id);\r\n txn.end(\"abandon\");\r\n\r\n code.value = \"bar\";\r\n const props2: TypeDefinitionElementProps = {\r\n classFullName: GenericGraphicalType2d.classFullName,\r\n model: IModel.dictionaryId,\r\n code,\r\n };\r\n const retryTxn = new EditTxn(db, \"cache cleared on abandonChanges retry\");\r\n retryTxn.start();\r\n const id2 = retryTxn.insertElement(props2);\r\n expect(id2).to.equal(id);\r\n const element2 = db.elements.getElementProps(id2);\r\n expect(element2).to.not.equal(element1);\r\n\r\n // Exercise the ECSqlStatement cache directly - nothing in the normal insert/read path above uses it anymore.\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n db.withPreparedStatement(\"SELECT ECInstanceId FROM BisCore:Element LIMIT 1\", () => { });\r\n\r\n // Make sure that the statement caches are not cleared\r\n expect((db as any)._sqliteStatementCache.size).to.be.greaterThan(0);\r\n expect((db as any)._statementCache.size).to.be.greaterThan(0);\r\n\r\n retryTxn.end(\"abandon\");\r\n db.close();\r\n });\r\n it(\"Only instance caches should be cleared with clearCaches instanceCachesOnly parameter\", () => {\r\n const standaloneFile = IModelTestUtils.prepareOutputFile(\"IModel\", \"StandaloneReadWrite.bim\");\r\n const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: \"Standalone\" } });\r\n const txn = new EditTxn(db, \"clearCaches instanceCachesOnly\");\r\n txn.start();\r\n\r\n const code = Code.createEmpty();\r\n code.value = \"foo\";\r\n const props: TypeDefinitionElementProps = {\r\n classFullName: GenericGraphicalType2d.classFullName,\r\n model: IModel.dictionaryId,\r\n code,\r\n };\r\n const id = txn.insertElement(props);\r\n db.elements.getElementProps(id);\r\n db.models.getModelProps(IModel.dictionaryId);\r\n // Exercise the ECSqlStatement cache directly - nothing in the normal insert/read path above uses it anymore.\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n db.withPreparedStatement(\"SELECT ECInstanceId FROM BisCore:Element LIMIT 1\", () => { });\r\n\r\n expect(db.elements[_cache].size).to.be.greaterThan(0);\r\n expect(db.models[_cache].size).to.be.greaterThan(0);\r\n expect(db.elements[_instanceKeyCache].size).to.be.greaterThan(0);\r\n expect(db.models[_instanceKeyCache].size).to.be.greaterThan(0);\r\n\r\n db.clearCaches({ instanceCachesOnly: true });\r\n\r\n expect(db.elements[_cache].size).to.equal(0);\r\n expect(db.models[_cache].size).to.equal(0);\r\n expect(db.elements[_instanceKeyCache].size).to.equal(0);\r\n expect(db.models[_instanceKeyCache].size).to.equal(0);\r\n\r\n // Make sure that the statement caches are not cleared\r\n expect((db as any)._sqliteStatementCache.size).to.be.greaterThan(0);\r\n expect((db as any)._statementCache.size).to.be.greaterThan(0);\r\n\r\n txn.end(\"abandon\");\r\n db.close();\r\n });\r\n it(\"inserting a second element with an empty code must not evict the first from the element props cache\", () => {\r\n const standaloneFile = IModelTestUtils.prepareOutputFile(\"IModel\", \"EmptyCodeCacheCollision.bim\");\r\n const db = StandaloneDb.createEmpty(standaloneFile, { rootSubject: { name: \"EmptyCodeCacheCollision\" } });\r\n\r\n withEditTxn(db, (txn) => {\r\n const categoryId = SpatialCategory.insert(txn, IModel.dictionaryId, \"TestCategory\", new SubCategoryAppearance());\r\n const modelId = PhysicalModel.insert(txn, IModel.rootSubjectId, \"TestModel\");\r\n\r\n const emptyCodeProps: GeometricElementProps = {\r\n classFullName: PhysicalObject.classFullName,\r\n model: modelId,\r\n category: categoryId,\r\n code: Code.createEmpty(),\r\n };\r\n\r\n // Insert the first element\r\n const id1 = txn.insertElement({ ...emptyCodeProps });\r\n db.elements.getElementProps(id1); // populate the element props cache\r\n const cacheSizeAfterFirstInsertAndRead = db.elements[_cache].size;\r\n expect(cacheSizeAfterFirstInsertAndRead).to.be.greaterThan(0, \"cache should be populated after getElementProps\");\r\n\r\n // Insert a second element with the same empty code\r\n const id2 = txn.insertElement({ ...emptyCodeProps });\r\n\r\n // The first element must still be in the cache.\r\n const cached1 = db.elements[_cache].get({ id: id1 });\r\n expect(cached1, \"first element should still be in cache after inserting second element with the same empty code\").to.not.be.undefined;\r\n expect(cached1!.elProps.id).to.equal(id1);\r\n\r\n expect(Id64.isValidId64(id1)).to.be.true;\r\n expect(Id64.isValidId64(id2)).to.be.true;\r\n expect(id1).to.not.equal(id2);\r\n });\r\n\r\n db.close();\r\n });\r\n it(\"Standalone iModel properties\", () => {\r\n const standaloneRootSubjectName = \"Standalone\";\r\n const standaloneFile1 = IModelTestUtils.prepareOutputFile(\"IModel\", \"Standalone1.bim\");\r\n const ecefLocation = new EcefLocation({ origin: [1, 2, 3], orientation: { yaw: 0, pitch: 0, roll: 0 } });\r\n const geographicCoordinateSystem = {\r\n horizontalCRS: { id: \"10TM115-27\" },\r\n };\r\n let standaloneDb1 = StandaloneDb.createEmpty(standaloneFile1, { rootSubject: { name: standaloneRootSubjectName }, ecefLocation, geographicCoordinateSystem });\r\n assert.isTrue(standaloneDb1.isStandaloneDb());\r\n assert.isTrue(standaloneDb1.isStandalone);\r\n assert.isFalse(standaloneDb1.isReadonly, \"Expect standalone iModels to be read-write during create\");\r\n assert.equal(standaloneDb1.getBriefcaseId(), BriefcaseIdValue.Unassigned);\r\n assert.equal(standaloneDb1.pathName, standaloneFile1);\r\n assert.equal(standaloneDb1, StandaloneDb.tryFindByKey(standaloneDb1.key), \"Should be in the list of open StandaloneDbs\");\r\n assert.equal(standaloneDb1.elements.getRootSubject().code.value, standaloneRootSubjectName);\r\n assert.isTrue(standaloneDb1.isOpen);\r\n assert.isTrue(Guid.isV4Guid(standaloneDb1.iModelId));\r\n assert.equal(standaloneDb1.iTwinId, Guid.empty);\r\n assert.strictEqual(\"\", standaloneDb1.changeset.id);\r\n assert.strictEqual(0, standaloneDb1.changeset.index);\r\n assert.deepEqual(standaloneDb1.ecefLocation?.origin, ecefLocation.origin, \"standalone ecefLocation should be set\");\r\n assert.strictEqual(standaloneDb1.geographicCoordinateSystem?.horizontalCRS?.id, \"10TM115-27\", \"standalone coordinate system should be set\");\r\n assert.equal(standaloneDb1.openMode, OpenMode.ReadWrite);\r\n standaloneDb1.close();\r\n assert.isFalse(standaloneDb1.isOpen);\r\n standaloneDb1.close(); // calling `close()` a second time is a no-op\r\n assert.isUndefined(StandaloneDb.tryFindByKey(standaloneDb1.key));\r\n standaloneDb1 = StandaloneDb.openFile(standaloneFile1);\r\n assert.equal(standaloneDb1, StandaloneDb.tryFindByKey(standaloneDb1.key));\r\n assert.isFalse(standaloneDb1.isReadonly, \"By default, StandaloneDbs are opened read/write\");\r\n standaloneDb1.close();\r\n assert.isUndefined(StandaloneDb.tryFindByKey(standaloneDb1.key));\r\n });\r\n it(\"Snapshot iModel properties\", async () => {\r\n const snapshotRootSubjectName = \"Snapshot\";\r\n const snapshotFile1 = IModelTestUtils.prepareOutputFile(\"IModel\", \"Snapshot1.bim\");\r\n const snapshotFile2 = IModelTestUtils.prepareOutputFile(\"IModel\", \"Snapshot2.bim\");\r\n const snapshotFile3 = IModelTestUtils.prepareOutputFile(\"IModel\", \"Snapshot3.bim\");\r\n const imodel = await importTestBim(createIModelFromSeed(\"test_for_snapshot.bim\", \"test.bim\"));\r\n const ecefLocation = new EcefLocation({ origin: [1, 2, 3], orientation: { yaw: 0, pitch: 0, roll: 0 } });\r\n const geographicCoordinateSystem = {\r\n horizontalCRS: { id: \"10TM115-27\" },\r\n };\r\n let snapshotDb1 = SnapshotDb.createEmpty(snapshotFile1, { rootSubject: { name: snapshotRootSubjectName }, createClassViews: true, ecefLocation, geographicCoordinateSystem });\r\n let snapshotDb2 = SnapshotDb.createFrom(snapshotDb1, snapshotFile2);\r\n let snapshotDb3 = SnapshotDb.createFrom(imodel, snapshotFile3, { createClassViews: true });\r\n assert.isTrue(snapshotDb1.isSnapshotDb());\r\n assert.isTrue(snapshotDb2.isSnapshotDb());\r\n assert.isTrue(snapshotDb3.isSnapshotDb());\r\n assert.isTrue(snapshotDb1.isSnapshot);\r\n assert.isTrue(snapshotDb2.isSnapshot);\r\n assert.isTrue(snapshotDb3.isSnapshot);\r\n assert.isFalse(snapshotDb1.isReadonly, \"Expect snapshots to be read-write during create\");\r\n assert.isFalse(snapshotDb2.isReadonly, \"Expect snapshots to be read-write during create\");\r\n assert.isFalse(snapshotDb3.isReadonly, \"Expect snapshots to be read-write during create\");\r\n assert.equal(snapshotDb1.getBriefcaseId(), BriefcaseIdValue.Unassigned);\r\n assert.equal(snapshotDb2.getBriefcaseId(), BriefcaseIdValue.Unassigned);\r\n assert.equal(snapshotDb3.getBriefcaseId(), BriefcaseIdValue.Unassigned);\r\n assert.equal(imodel.getBriefcaseId(), BriefcaseIdValue.Unassigned);\r\n assert.equal(snapshotDb1.pathName, snapshotFile1);\r\n assert.equal(snapshotDb2.pathName, snapshotFile2);\r\n assert.equal(snapshotDb3.pathName, snapshotFile3);\r\n assert.equal(snapshotDb1, SnapshotDb.tryFindByKey(snapshotDb1.key));\r\n assert.equal(snapshotDb2, SnapshotDb.tryFindByKey(snapshotDb2.key));\r\n assert.equal(snapshotDb3, SnapshotDb.tryFindByKey(snapshotDb3.key));\r\n const iModelGuid1: GuidString = snapshotDb1.iModelId;\r\n const iModelGuid2: GuidString = snapshotDb2.iModelId;\r\n const iModelGuid3: GuidString = snapshotDb3.iModelId;\r\n assert.notEqual(iModelGuid1, iModelGuid2, \"Expect different iModel GUIDs for each snapshot\");\r\n assert.notEqual(iModelGuid2, iModelGuid3, \"Expect different iModel GUIDs for each snapshot\");\r\n const rootSubjectName1 = snapshotDb1.elements.getRootSubject().code.value;\r\n const rootSubjectName2 = snapshotDb2.elements.getRootSubject().code.value;\r\n const rootSubjectName3 = snapshotDb3.elements.getRootSubject().code.value;\r\n const imodelRootSubjectName = imodel.elements.getRootSubject().code.value;\r\n assert.equal(rootSubjectName1, snapshotRootSubjectName);\r\n assert.equal(rootSubjectName1, rootSubjectName2, \"Expect a snapshot to maintain the root Subject name from its seed\");\r\n assert.equal(rootSubjectName3, imodelRootSubjectName, \"Expect a snapshot to maintain the root Subject name from its seed\");\r\n assert.isTrue(snapshotDb1.isOpen);\r\n assert.isTrue(snapshotDb2.isOpen);\r\n assert.isTrue(snapshotDb3.isOpen);\r\n assert.deepEqual(snapshotDb1.ecefLocation?.origin, ecefLocation.origin, \"snapshot ecefLocation should be set\");\r\n assert.strictEqual(snapshotDb1.geographicCoordinateSystem?.horizontalCRS?.id, \"10TM115-27\", \"snapshot coordinate system should be set\");\r\n snapshotDb1.close();\r\n snapshotDb2.close();\r\n snapshotDb3.close();\r\n assert.isFalse(snapshotDb1.isOpen);\r\n assert.isFalse(snapshotDb2.isOpen);\r\n assert.isFalse(snapshotDb3.isOpen);\r\n snapshotDb1.close(); // calling `close()` a second time is a no-op\r\n snapshotDb2.close(); // calling `close()` a second time is a no-op\r\n snapshotDb3.close(); // calling `close()` a second time is a no-op\r\n assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb1.key));\r\n assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb2.key));\r\n assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb3.key));\r\n snapshotDb1 = SnapshotDb.openFile(snapshotFile1);\r\n snapshotDb2 = SnapshotDb.openFile(snapshotFile2);\r\n snapshotDb3 = SnapshotDb.openFile(snapshotFile3);\r\n assert.equal(snapshotDb1, SnapshotDb.tryFindByKey(snapshotDb1.key));\r\n assert.equal(snapshotDb2, SnapshotDb.tryFindByKey(snapshotDb2.key));\r\n assert.equal(snapshotDb3, SnapshotDb.tryFindByKey(snapshotDb3.key));\r\n assert.equal(snapshotDb3, SnapshotDb.findByKey(snapshotDb3.key));\r\n assert.equal(snapshotDb3, IModelDb.findByKey(snapshotDb3.key));\r\n assert.throws(() => BriefcaseDb.findByKey(snapshotDb1.key)); // lookup of key for SnapshotDb via BriefcaseDb should throw\r\n assert.throws(() => StandaloneDb.findByKey(snapshotDb1.key)); // likewise for StandaloneDb\r\n assert.isTrue(snapshotDb1.isReadonly, \"Expect snapshots to be read-only after open\");\r\n assert.isTrue(snapshotDb2.isReadonly, \"Expect snapshots to be read-only after open\");\r\n assert.isTrue(snapshotDb3.isReadonly, \"Expect snapshots to be read-only after open\");\r\n assert.isTrue(hasClassView(snapshotDb1, \"bis.Element\"));\r\n assert.isTrue(hasClassView(snapshotDb1, \"bis.ElementAspect\"));\r\n assert.isTrue(hasClassView(snapshotDb1, \"bis.Model\"));\r\n assert.isTrue(hasClassView(snapshotDb1, \"bis.ElementRefersToElements\"));\r\n assert.isFalse(hasClassView(snapshotDb2, \"bis.Element\"));\r\n assert.isTrue(hasClassView(snapshotDb3, \"bis.Element\"));\r\n\r\n imodel.close();\r\n snapshotDb1.close();\r\n snapshotDb2.close();\r\n snapshotDb3.close();\r\n\r\n assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb1.key));\r\n assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb2.key));\r\n assert.isUndefined(SnapshotDb.tryFindByKey(snapshotDb3.key));\r\n });\r\n it(\"upgrade the domain schema in a StandaloneDb\", async () => {\r\n const testFileName = IModelTestUtils.prepareOutputFile(\"UpgradeIModel\", \"testImodel.bim\");\r\n const seedFileName = IModelTestUtils.resolveAssetFile(\"testImodel.bim\");\r\n IModelJsFs.copySync(seedFileName, testFileName);\r\n\r\n let iModel = StandaloneDb.openFile(testFileName, OpenMode.ReadWrite);\r\n const beforeVersion = iModel.querySchemaVersion(\"BisCore\");\r\n assert.isTrue(semver.satisfies(beforeVersion!, \"= 1.0.0\"));\r\n iModel.close();\r\n\r\n const schemaState: SchemaState = StandaloneDb.validateSchemas(testFileName, true);\r\n assert.strictEqual(schemaState, SchemaState.UpgradeRecommended);\r\n\r\n StandaloneDb.upgradeStandaloneSchemas(testFileName);\r\n\r\n iModel = StandaloneDb.openFile(testFileName, OpenMode.ReadWrite);\r\n const afterVersion = iModel.querySchemaVersion(\"BisCore\");\r\n assert.isTrue(semver.satisfies(afterVersion!, \">= 1.0.10\"));\r\n iModel.close();\r\n });\r\n it(\"throws NotFound when attempting to access element props after closing the iModel\", () => {\r\n const imodelPath = IModelTestUtils.prepareOutputFile(\"IModel\", \"accessAfterClose.bim\");\r\n const imodel = SnapshotDb.createEmpty(imodelPath, { rootSubject: { name: \"accessAfterClose\" } });\r\n\r\n const elem = imodel.elements.getElement<Subject>(IModel.rootSubjectId);\r\n expect(elem.id).to.equal(IModel.rootSubjectId);\r\n\r\n imodel.close();\r\n\r\n expect(() => imodel.elements.getElement<Subject>(IModel.rootSubjectId)).to.throw(IModelError, \"Element=0x1\", \"Not Found\");\r\n });\r\n it(\"should provide meaningful error when querying a closed iModel\", () => {\r\n const testImodel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile(\"IModel\", \"QueryingClosedImodel.bim\"), { rootSubject: { name: \"QueryClosedTest\" } });\r\n assert.isTrue(testImodel.isOpen);\r\n\r\n // Close the iModel for the tests\r\n testImodel.close();\r\n assert.isFalse(testImodel.isOpen);\r\n\r\n const closedDbError = \"db not open\";\r\n expect(() => testImodel.withPreparedSqliteStatement(\"SELECT 1\", () => { })).to.throw(closedDbError);\r\n expect(() => testImodel.withPreparedSqliteStatement(\"SELECT 1\", () => { })).to.throw(closedDbError);\r\n expect(() => testImodel.prepareSqliteStatement(\"SELECT 1\")).to.throw(closedDbError);\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n expect(() => testImodel.prepareStatement(\"SELECT 1\")).to.throw(closedDbError);\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n expect(() => testImodel.withPreparedStatement(\"SELECT ECInstanceId FROM BisCore:Element LIMIT 1\", () => { })).to.throw(closedDbError);\r\n expect(() => testImodel.elements.queryChildren(IModel.rootSubjectId)).to.throw(closedDbError);\r\n expect(() => testImodel.elements.getAspects(\"0x1\", \"WrongSchema:WrongClass\")).to.throw(closedDbError);\r\n expect(() => testImodel.createQueryReader(\"SELECT 1\")).to.throw(closedDbError);\r\n });\r\n});\r\n\r\ndescribe(\"IModelDb.requireMinimumSchemaVersion\", () => {\r\n let imodel: SnapshotDb;\r\n\r\n before(async () => {\r\n await TestUtils.startBackend();\r\n imodel = SnapshotDb.createEmpty(IModelTestUtils.prepareOutputFile(\"IModel\", \"MinSchemaVer.bim\"), { rootSubject: { name: \"MinSchemaVer\" } });\r\n });\r\n\r\n after(() => {\r\n imodel.close();\r\n });\r\n\r\n it(\"throws if the schema does not exist\", () => {\r\n expect(\r\n () => imodel.requireMinimumSchemaVersion(\"FakeSchema\", new ECVersion(1, 0, 0), \"Scrobbles\")\r\n ).to.throw(\"Scrobbles requires FakeSchema v01.00.00 or newer\");\r\n });\r\n\r\n it(\"throws IFF the schema version is older than the minimum\", () => {\r\n function test(minVer: ECVersion, expectError: boolean): void {\r\n expect(imodel.meetsMinimumSchemaVersion(\"BisCore\", minVer)).to.equal(!expectError);\r\n const require = () => imodel.requireMinimumSchemaVersion(\"BisCore\", minVer, \"Scrobbles\");\r\n if (expectError) {\r\n expect(require).to.throw(`Scrobbles requires BisCore v${minVer.toString()} or newer`);\r\n } else {\r\n require();\r\n }\r\n }\r\n\r\n const bisVer = imodel.querySchemaVersionNumbers(\"BisCore\")!;\r\n expect(bisVer.read).to.equal(1);\r\n expect(bisVer.write).to.equal(0);\r\n expect(bisVer.minor).to.least(24);\r\n\r\n test(bisVer, false);\r\n test(new ECVersion(bisVer.read, bisVer.write, bisVer.minor - 1), false);\r\n test(new ECVersion(0, 0, 1), false);\r\n\r\n test(new ECVersion(bisVer.read, bisVer.write, bisVer.minor + 1), true);\r\n test(new ECVersion(bisVer.read, bisVer.write, bisVer.minor + 1), true);\r\n test(new ECVersion(bisVer.read + 1, bisVer.write + 1, bisVer.minor), true);\r\n });\r\n});"]}
|