@itwin/core-backend 5.10.0-dev.10 → 5.10.0-dev.12
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/lib/cjs/Category.d.ts +4 -4
- package/lib/cjs/Category.js.map +1 -1
- package/lib/cjs/ChangesetECAdaptor.d.ts +6 -6
- package/lib/cjs/ChangesetECAdaptor.js +4 -4
- 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/Element.d.ts +10 -10
- package/lib/cjs/Element.js +2 -2
- package/lib/cjs/Element.js.map +1 -1
- package/lib/cjs/ElementAspect.d.ts +1 -1
- package/lib/cjs/ElementAspect.js.map +1 -1
- package/lib/cjs/ElementTreeWalker.d.ts +5 -5
- package/lib/cjs/ElementTreeWalker.js.map +1 -1
- package/lib/cjs/ExternalSource.d.ts +2 -2
- package/lib/cjs/ExternalSource.js.map +1 -1
- package/lib/cjs/IModelDb.d.ts +33 -23
- package/lib/cjs/IModelDb.d.ts.map +1 -1
- package/lib/cjs/IModelDb.js +32 -20
- package/lib/cjs/IModelDb.js.map +1 -1
- package/lib/cjs/LineStyle.d.ts +6 -6
- package/lib/cjs/LineStyle.js.map +1 -1
- package/lib/cjs/LocalHub.d.ts +6 -0
- package/lib/cjs/LocalHub.d.ts.map +1 -1
- package/lib/cjs/LocalHub.js +23 -0
- package/lib/cjs/LocalHub.js.map +1 -1
- package/lib/cjs/Material.d.ts +1 -1
- package/lib/cjs/Material.js.map +1 -1
- package/lib/cjs/Model.d.ts +6 -6
- package/lib/cjs/Model.js.map +1 -1
- package/lib/cjs/Relationship.d.ts +10 -10
- package/lib/cjs/Relationship.js +6 -6
- package/lib/cjs/Relationship.js.map +1 -1
- package/lib/cjs/SheetIndex.d.ts +4 -4
- package/lib/cjs/SheetIndex.js.map +1 -1
- package/lib/cjs/Texture.d.ts +1 -1
- package/lib/cjs/Texture.js.map +1 -1
- package/lib/cjs/ViewDefinition.d.ts +6 -6
- package/lib/cjs/ViewDefinition.js.map +1 -1
- package/lib/cjs/annotations/ElementDrivesTextAnnotation.d.ts +1 -1
- package/lib/cjs/annotations/ElementDrivesTextAnnotation.js.map +1 -1
- package/lib/cjs/annotations/FrameGeometry.d.ts.map +1 -1
- package/lib/cjs/annotations/FrameGeometry.js +2 -3
- package/lib/cjs/annotations/FrameGeometry.js.map +1 -1
- package/lib/cjs/domains/FunctionalElements.d.ts +1 -1
- package/lib/cjs/domains/FunctionalElements.js.map +1 -1
- package/lib/cjs/domains/GenericElements.d.ts +2 -2
- package/lib/cjs/domains/GenericElements.js.map +1 -1
- package/lib/cjs/internal/ChannelAdmin.d.ts +2 -2
- package/lib/cjs/internal/ChannelAdmin.js.map +1 -1
- package/lib/cjs/internal/HubMock.d.ts +24 -1
- package/lib/cjs/internal/HubMock.d.ts.map +1 -1
- package/lib/cjs/internal/HubMock.js +60 -39
- package/lib/cjs/internal/HubMock.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 +6 -6
- package/lib/esm/ChangesetECAdaptor.js +4 -4
- 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/Element.d.ts +10 -10
- package/lib/esm/Element.js +2 -2
- package/lib/esm/Element.js.map +1 -1
- package/lib/esm/ElementAspect.d.ts +1 -1
- package/lib/esm/ElementAspect.js.map +1 -1
- package/lib/esm/ElementTreeWalker.d.ts +5 -5
- package/lib/esm/ElementTreeWalker.js.map +1 -1
- package/lib/esm/ExternalSource.d.ts +2 -2
- package/lib/esm/ExternalSource.js.map +1 -1
- package/lib/esm/IModelDb.d.ts +33 -23
- package/lib/esm/IModelDb.d.ts.map +1 -1
- package/lib/esm/IModelDb.js +32 -20
- package/lib/esm/IModelDb.js.map +1 -1
- package/lib/esm/LineStyle.d.ts +6 -6
- package/lib/esm/LineStyle.js.map +1 -1
- package/lib/esm/LocalHub.d.ts +6 -0
- package/lib/esm/LocalHub.d.ts.map +1 -1
- package/lib/esm/LocalHub.js +23 -0
- package/lib/esm/LocalHub.js.map +1 -1
- package/lib/esm/Material.d.ts +1 -1
- package/lib/esm/Material.js.map +1 -1
- package/lib/esm/Model.d.ts +6 -6
- package/lib/esm/Model.js.map +1 -1
- package/lib/esm/Relationship.d.ts +10 -10
- package/lib/esm/Relationship.js +6 -6
- package/lib/esm/Relationship.js.map +1 -1
- package/lib/esm/SheetIndex.d.ts +4 -4
- package/lib/esm/SheetIndex.js.map +1 -1
- package/lib/esm/Texture.d.ts +1 -1
- package/lib/esm/Texture.js.map +1 -1
- package/lib/esm/ViewDefinition.d.ts +6 -6
- package/lib/esm/ViewDefinition.js.map +1 -1
- package/lib/esm/annotations/ElementDrivesTextAnnotation.d.ts +1 -1
- package/lib/esm/annotations/ElementDrivesTextAnnotation.js.map +1 -1
- package/lib/esm/annotations/FrameGeometry.d.ts.map +1 -1
- package/lib/esm/annotations/FrameGeometry.js +2 -3
- package/lib/esm/annotations/FrameGeometry.js.map +1 -1
- package/lib/esm/domains/FunctionalElements.d.ts +1 -1
- package/lib/esm/domains/FunctionalElements.js.map +1 -1
- package/lib/esm/domains/GenericElements.d.ts +2 -2
- package/lib/esm/domains/GenericElements.js.map +1 -1
- package/lib/esm/internal/ChannelAdmin.d.ts +2 -2
- package/lib/esm/internal/ChannelAdmin.js.map +1 -1
- package/lib/esm/internal/HubMock.d.ts +24 -1
- package/lib/esm/internal/HubMock.d.ts.map +1 -1
- package/lib/esm/internal/HubMock.js +61 -40
- package/lib/esm/internal/HubMock.js.map +1 -1
- package/lib/esm/test/SchemaChangesetCanBeReversed.test.d.ts +2 -0
- package/lib/esm/test/SchemaChangesetCanBeReversed.test.d.ts.map +1 -0
- package/lib/esm/test/SchemaChangesetCanBeReversed.test.js +239 -0
- package/lib/esm/test/SchemaChangesetCanBeReversed.test.js.map +1 -0
- package/lib/esm/test/annotations/FrameGeometry.test.js +2 -1
- package/lib/esm/test/annotations/FrameGeometry.test.js.map +1 -1
- package/lib/esm/test/standalone/DeleteElements.test.js +45 -0
- package/lib/esm/test/standalone/DeleteElements.test.js.map +1 -1
- package/package.json +13 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HubMock.js","sourceRoot":"","sources":["../../../src/internal/HubMock.ts"],"names":[],"mappings":"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","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\n\r\nimport { join } from \"path\";\r\nimport { Guid, GuidString } from \"@itwin/core-bentley\";\r\nimport {\r\n ChangesetFileProps, ChangesetIndex, ChangesetIndexOrId, ChangesetProps, ChangesetRange, IModelVersion, LocalDirName,\r\n} from \"@itwin/core-common\";\r\nimport {\r\n AcquireNewBriefcaseIdArg,\r\n BackendHubAccess, BriefcaseDbArg, BriefcaseIdArg, ChangesetArg, CreateNewIModelProps, DownloadChangesetArg, DownloadChangesetRangeArg, IModelIdArg, IModelNameArg,\r\n LockMap, LockProps, V2CheckpointAccessProps,\r\n} from \"../BackendHubAccess\";\r\nimport { CheckpointProps, DownloadRequest, MockCheckpoint, ProgressFunction, ProgressStatus, V2CheckpointManager } from \"../CheckpointManager\";\r\nimport { IModelHost } from \"../IModelHost\";\r\nimport { IModelJsFs } from \"../IModelJsFs\";\r\nimport { LocalHub } from \"../LocalHub\";\r\nimport { TokenArg } from \"../IModelDb\";\r\nimport { _getHubAccess, _mockCheckpoint, _setHubAccess } from \"./Symbols\";\r\nimport { BriefcaseManager } from \"../BriefcaseManager\";\r\nimport * as path from \"path\";\r\n\r\nfunction wasStarted(val: string | undefined): asserts val is string {\r\n if (undefined === val)\r\n throw new Error(\"Call HubMock.startup first\");\r\n}\r\n\r\nfunction doDownload(args: { iModelId: string, changeset: ChangesetIndexOrId, targetFile: string }) {\r\n HubMock.findLocalHub(args.iModelId).downloadCheckpoint(args);\r\n}\r\nconst mockCheckpoint: MockCheckpoint = {\r\n mockAttach: (checkpoint: CheckpointProps) => {\r\n const targetFile = path.join(BriefcaseManager.getBriefcaseBasePath(checkpoint.iModelId), `${checkpoint.changeset.index}.bim`);\r\n doDownload({ ...checkpoint, targetFile })\r\n return targetFile;\r\n },\r\n\r\n mockDownload: (request: DownloadRequest) => {\r\n doDownload({ ...request.checkpoint, targetFile: request.localFile });\r\n }\r\n};\r\n\r\n/**\r\n * Mocks iModelHub for testing creating Briefcases, downloading checkpoints, and simulating multiple users pushing and pulling changesets, etc.\r\n *\r\n * Generally, tests for apis that *create or modify* iModels can and should be mocked. Otherwise they:\r\n * - create tremendous load on the test servers when they run on programmer's desktops and in CI jobs\r\n * - waste network and data center resources (i.e. $$$s),\r\n * - interfere with other tests running on the same or other systems, and\r\n * - (far worse) are the source of test flakiness outside of the api being tested.\r\n *\r\n * This class can be used to create tests that do not require authentication, are synchronous,\r\n * are guaranteed to be self-contained (i.e. do not interfere with other tests running at the same time or later), and do not fail for reasons outside\r\n * of the control of the test itself. As a bonus, in addition to making tests more reliable, mocking IModelHub generally makes tests run *much* faster.\r\n *\r\n * On the other hand, tests that expect to find an existing iModels, checkpoints, changesets, etc. in IModelHub cannot be mocked. In that case, those tests\r\n * should be careful to NOT modify the data, since doing so causes interference with other tests running simultaneously. These tests should be limited to\r\n * low level testing of the core apis only.\r\n *\r\n * To initialize HubMock, call [[startup]] at the beginning of your test, usually in `describe.before`. Thereafter, all access to iModelHub for an iModel will be\r\n * directed to a [[LocalHub]] - your test code does not change. After the test(s) complete, call [[shutdown]] (usually in `describe.after`) to stop mocking IModelHub and clean\r\n * up any resources used by the test(s). If you want to mock a single test, call [[startup]] as the first line and [[shutdown]] as the last. If you wish to run the\r\n * test against a \"real\" IModelHub, you can simply comment off the call [[startup]], though in that case you should make sure the name of your\r\n * iModel is unique so your test won't collide with other tests (iModel name uniqueness is not necessary for mocked tests.)\r\n *\r\n * Mocked tests must always start by creating a new iModel via [[IModelHost[_hubAccess].createNewIModel]] with a `version0` iModel.\r\n * They use mock (aka \"bogus\") credentials for `AccessTokens`, which is fine since [[HubMock]] never accesses resources outside the current\r\n * computer.\r\n *\r\n * @note Only one HubMock at a time, *running in a single process*, may be active. The comments above about multiple simultaneous tests refer to tests\r\n * running on different computers, or on a single computer in multiple processes. All of those scenarios are problematic without mocking.\r\n *\r\n * @internal\r\n */\r\nexport class HubMock {\r\n private static mockRoot: LocalDirName | undefined;\r\n private static hubs = new Map<string, LocalHub>();\r\n private static _saveHubAccess: BackendHubAccess | undefined;\r\n private static _iTwinId: GuidString | undefined;\r\n\r\n /** Determine whether a test us currently being run under HubMock */\r\n public static get isValid() { return undefined !== this.mockRoot; }\r\n public static get iTwinId() {\r\n wasStarted(this._iTwinId);\r\n return this._iTwinId;\r\n }\r\n\r\n /**\r\n * Begin mocking IModelHub access. After this call, all access to IModelHub will be directed to a [[LocalHub]].\r\n * @param mockName a unique name (e.g. \"MyTest\") for this HubMock to disambiguate tests when more than one is simultaneously active.\r\n * It is used to create a private directory used by the HubMock for a test. That directory is removed when [[shutdown]] is called.\r\n */\r\n public static startup(mockName: LocalDirName, outputDir: string) {\r\n if (this.isValid)\r\n throw new Error(\"Either a previous test did not call HubMock.shutdown() properly, or more than one test is simultaneously attempting to use HubMock, which is not allowed\");\r\n\r\n this.hubs.clear();\r\n this.mockRoot = join(outputDir, \"HubMock\", mockName);\r\n IModelJsFs.recursiveMkDirSync(this.mockRoot);\r\n IModelJsFs.purgeDirSync(this.mockRoot);\r\n this._saveHubAccess = IModelHost[_getHubAccess]();\r\n\r\n IModelHost[_setHubAccess](this);\r\n HubMock._iTwinId = Guid.createValue(); // all iModels for this test get the same \"iTwinId\"\r\n\r\n V2CheckpointManager[_mockCheckpoint] = mockCheckpoint;\r\n }\r\n\r\n /** Stop a HubMock that was previously started with [[startup]]\r\n * @note this function throws an exception if any of the iModels used during the tests are left open.\r\n */\r\n public static shutdown() {\r\n if (this.mockRoot === undefined)\r\n return;\r\n\r\n V2CheckpointManager[_mockCheckpoint] = undefined;\r\n\r\n HubMock._iTwinId = undefined;\r\n for (const hub of this.hubs)\r\n hub[1].cleanup();\r\n\r\n this.hubs.clear();\r\n IModelJsFs.purgeDirSync(this.mockRoot);\r\n IModelJsFs.removeSync(this.mockRoot);\r\n IModelHost[_setHubAccess](this._saveHubAccess);\r\n this.mockRoot = undefined;\r\n }\r\n\r\n public static findLocalHub(iModelId: GuidString): LocalHub {\r\n const hub = this.hubs.get(iModelId);\r\n if (!hub)\r\n throw new Error(`local hub for iModel ${iModelId} not created`);\r\n return hub;\r\n }\r\n\r\n /** create a [[LocalHub]] for an iModel. */\r\n public static async createNewIModel(arg: CreateNewIModelProps): Promise<GuidString> {\r\n wasStarted(this.mockRoot);\r\n const props = { ...arg, iModelId: Guid.createValue() };\r\n const mock = new LocalHub(join(this.mockRoot, props.iModelId), props);\r\n this.hubs.set(props.iModelId, mock);\r\n return props.iModelId;\r\n }\r\n\r\n /** remove the [[LocalHub]] for an iModel */\r\n public static destroy(iModelId: GuidString) {\r\n this.findLocalHub(iModelId).cleanup();\r\n this.hubs.delete(iModelId);\r\n }\r\n\r\n /** All methods below are mocks of the [[BackendHubAccess]] interface */\r\n\r\n public static async getChangesetFromNamedVersion(arg: IModelIdArg & { versionName: string }): Promise<ChangesetProps> {\r\n return this.findLocalHub(arg.iModelId).findNamedVersion(arg.versionName);\r\n }\r\n\r\n private static changesetIndexFromArg(arg: ChangesetArg) {\r\n return (undefined !== arg.changeset.index) ? arg.changeset.index : this.findLocalHub(arg.iModelId).getChangesetIndex(arg.changeset.id);\r\n }\r\n\r\n public static async getChangesetFromVersion(arg: IModelIdArg & { version: IModelVersion }): Promise<ChangesetProps> {\r\n const hub = this.findLocalHub(arg.iModelId);\r\n const version = arg.version;\r\n if (version.isFirst)\r\n return hub.getChangesetByIndex(0);\r\n\r\n const asOf = version.getAsOfChangeSet();\r\n if (asOf)\r\n return hub.getChangesetById(asOf);\r\n\r\n const versionName = version.getName();\r\n if (versionName)\r\n return hub.findNamedVersion(versionName);\r\n\r\n return hub.getLatestChangeset();\r\n }\r\n\r\n public static async getLatestChangeset(arg: IModelIdArg): Promise<ChangesetProps> {\r\n return this.findLocalHub(arg.iModelId).getLatestChangeset();\r\n }\r\n\r\n private static async getAccessToken(arg: TokenArg) {\r\n return arg.accessToken ?? await IModelHost.getAccessToken();\r\n }\r\n\r\n public static async getMyBriefcaseIds(arg: IModelIdArg): Promise<number[]> {\r\n const accessToken = await this.getAccessToken(arg);\r\n return this.findLocalHub(arg.iModelId).getBriefcaseIds(accessToken);\r\n }\r\n\r\n public static async acquireNewBriefcaseId(arg: AcquireNewBriefcaseIdArg): Promise<number> {\r\n const accessToken = await this.getAccessToken(arg);\r\n return this.findLocalHub(arg.iModelId).acquireNewBriefcaseId(accessToken, arg.briefcaseAlias);\r\n }\r\n\r\n /** Release a briefcaseId. After this call it is illegal to generate changesets for the released briefcaseId. */\r\n public static async releaseBriefcase(arg: BriefcaseIdArg): Promise<void> {\r\n return this.findLocalHub(arg.iModelId).releaseBriefcaseId(arg.briefcaseId);\r\n }\r\n\r\n public static async downloadChangeset(arg: DownloadChangesetArg): Promise<ChangesetFileProps> {\r\n const changesetProps = this.findLocalHub(arg.iModelId).downloadChangeset({ index: this.changesetIndexFromArg(arg), targetDir: arg.targetDir });\r\n\r\n if (arg.progressCallback) {\r\n const totalSize = IModelJsFs.lstatSync(changesetProps.pathname)?.size;\r\n if (totalSize)\r\n await HubMock.mockProgressReporting(arg.progressCallback, totalSize);\r\n }\r\n\r\n return changesetProps;\r\n }\r\n\r\n public static async downloadChangesets(arg: DownloadChangesetRangeArg): Promise<ChangesetFileProps[]> {\r\n const changesetProps = this.findLocalHub(arg.iModelId).downloadChangesets({ range: arg.range, targetDir: arg.targetDir });\r\n\r\n if (arg.progressCallback) {\r\n const totalSize = changesetProps.reduce((sum, props) => sum + (IModelJsFs.lstatSync(props.pathname)?.size ?? 0), 0);\r\n await HubMock.mockProgressReporting(arg.progressCallback, totalSize);\r\n }\r\n\r\n return changesetProps;\r\n }\r\n\r\n public static async queryChangeset(arg: ChangesetArg): Promise<ChangesetProps> {\r\n return this.findLocalHub(arg.iModelId).getChangesetByIndex(this.changesetIndexFromArg(arg));\r\n }\r\n\r\n public static async queryChangesets(arg: IModelIdArg & { range?: ChangesetRange }): Promise<ChangesetProps[]> {\r\n return this.findLocalHub(arg.iModelId).queryChangesets(arg.range);\r\n }\r\n\r\n public static async pushChangeset(arg: IModelIdArg & { changesetProps: ChangesetFileProps }): Promise<ChangesetIndex> {\r\n return this.findLocalHub(arg.iModelId).addChangeset(arg.changesetProps);\r\n }\r\n\r\n public static async queryV2Checkpoint(arg: CheckpointProps): Promise<V2CheckpointAccessProps | undefined> {\r\n return {\r\n accountName: \"none\",\r\n sasToken: \"none\",\r\n containerId: Guid.createValue(),\r\n dbName: `${arg.changeset.index ?? 0}.bim`,\r\n storageType: \"mock\",\r\n isMock: true,\r\n checkpoint: arg,\r\n } as V2CheckpointAccessProps;\r\n }\r\n\r\n public static async releaseAllLocks(arg: BriefcaseDbArg) {\r\n const hub = this.findLocalHub(arg.iModelId);\r\n hub.releaseAllLocks({ briefcaseId: arg.briefcaseId, changesetIndex: hub.getIndexFromChangeset(arg.changeset) });\r\n }\r\n\r\n public static async abandonAllLocks(arg: BriefcaseIdArg): Promise<void> {\r\n const hub = this.findLocalHub(arg.iModelId);\r\n hub.abandonAllLocks(arg);\r\n }\r\n\r\n public static async queryAllLocks(_arg: BriefcaseDbArg): Promise<LockProps[]> {\r\n return [];\r\n }\r\n\r\n public static async acquireLocks(arg: BriefcaseDbArg, locks: LockMap): Promise<void> {\r\n this.findLocalHub(arg.iModelId).acquireLocks(locks, arg);\r\n }\r\n\r\n public static async abandonLocks(arg: BriefcaseIdArg, locks: LockMap): Promise<void> {\r\n this.findLocalHub(arg.iModelId).abandonLocks(locks, arg);\r\n }\r\n\r\n public static async queryIModelByName(arg: IModelNameArg): Promise<GuidString | undefined> {\r\n for (const hub of this.hubs) {\r\n const localHub = hub[1];\r\n if (localHub.iTwinId === arg.iTwinId && localHub.iModelName === arg.iModelName)\r\n return localHub.iModelId;\r\n }\r\n return undefined;\r\n }\r\n\r\n public static async deleteIModel(arg: IModelIdArg & { iTwinId: GuidString }): Promise<void> {\r\n return this.destroy(arg.iModelId);\r\n }\r\n\r\n private static async mockProgressReporting(progressCallback: ProgressFunction, totalSize: number): Promise<void> {\r\n await new Promise((resolve, reject) => {\r\n let rejected = false;\r\n\r\n const mockProgress = (index: number) => {\r\n const bytesDownloaded = Math.floor(totalSize * (index / 4));\r\n if (!rejected && progressCallback(bytesDownloaded, totalSize) === ProgressStatus.Abort) {\r\n rejected = true;\r\n reject(new Error(\"AbortError\"));\r\n }\r\n };\r\n\r\n mockProgress(1);\r\n setTimeout(() => mockProgress(2), 50);\r\n setTimeout(() => mockProgress(3), 100);\r\n setTimeout(() => {\r\n mockProgress(4);\r\n resolve(undefined);\r\n }, 150);\r\n });\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"HubMock.js","sourceRoot":"","sources":["../../../src/internal/HubMock.ts"],"names":[],"mappings":"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","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\n\r\nimport { join } from \"path\";\r\nimport { Guid, GuidString } from \"@itwin/core-bentley\";\r\nimport {\r\n ChangesetFileProps, ChangesetIndex, ChangesetIndexOrId, ChangesetProps, ChangesetRange, IModelVersion, LocalDirName,\r\n} from \"@itwin/core-common\";\r\nimport {\r\n AcquireNewBriefcaseIdArg,\r\n BackendHubAccess, BriefcaseDbArg, BriefcaseIdArg, ChangesetArg, CreateNewIModelProps, DownloadChangesetArg, DownloadChangesetRangeArg, IModelIdArg, IModelNameArg,\r\n LockMap, LockProps, V2CheckpointAccessProps,\r\n} from \"../BackendHubAccess\";\r\nimport { CheckpointProps, DownloadRequest, MockCheckpoint, ProgressFunction, ProgressStatus, V2CheckpointManager } from \"../CheckpointManager\";\r\nimport { IModelHost } from \"../IModelHost\";\r\nimport { IModelJsFs } from \"../IModelJsFs\";\r\nimport { LocalHub } from \"../LocalHub\";\r\nimport { SnapshotDb, TokenArg } from \"../IModelDb\";\r\nimport { _getHubAccess, _mockCheckpoint, _nativeDb, _setHubAccess } from \"./Symbols\";\r\nimport { BriefcaseManager } from \"../BriefcaseManager\";\r\n\r\nfunction wasStarted(val: string | undefined): asserts val is string {\r\n if (undefined === val)\r\n throw new Error(\"Call HubMock.startup first\");\r\n}\r\n\r\n// Used by mockAttach: copies the nearest *prior* checkpoint (never newer) so the\r\n// returned file is already at or before the requested version.\r\nfunction doDownloadPrior(args: { iModelId: string, changeset: ChangesetIndexOrId, targetFile: string }) {\r\n HubMock.findLocalHub(args.iModelId).downloadCheckpoint(args);\r\n}\r\n\r\n// Used by mockDownload: copies the *nearest* checkpoint (forward or backward).\r\n// When the nearest is newer than the requested version, CheckpointManager.updateToRequestedVersion\r\n// will reverse it to the requested version via BriefcaseManager.pullAndApplyChangesets.\r\nfunction doDownloadNearest(args: { iModelId: string, changeset: ChangesetIndexOrId, targetFile: string }) {\r\n const hub = HubMock.findLocalHub(args.iModelId);\r\n const requestedIndex = hub.getIndexFromChangeset(args.changeset);\r\n const nearest = hub.queryNearestCheckpoint(requestedIndex);\r\n IModelJsFs.copySync(join(hub.checkpointDir, hub.checkpointNameFromIndex(nearest)), args.targetFile);\r\n}\r\n\r\nconst mockCheckpoint: MockCheckpoint = {\r\n mockAttach: (checkpoint: CheckpointProps) => {\r\n const targetFile = join(BriefcaseManager.getBriefcaseBasePath(checkpoint.iModelId), `${checkpoint.changeset.index}.bim`);\r\n doDownloadPrior({ ...checkpoint, targetFile });\r\n return targetFile;\r\n },\r\n\r\n mockDownload: (request: DownloadRequest) => {\r\n doDownloadNearest({ ...request.checkpoint, targetFile: request.localFile });\r\n }\r\n};\r\n\r\n/**\r\n * Mocks iModelHub for testing creating Briefcases, downloading checkpoints, and simulating multiple users pushing and pulling changesets, etc.\r\n *\r\n * Generally, tests for apis that *create or modify* iModels can and should be mocked. Otherwise they:\r\n * - create tremendous load on the test servers when they run on programmer's desktops and in CI jobs\r\n * - waste network and data center resources (i.e. $$$s),\r\n * - interfere with other tests running on the same or other systems, and\r\n * - (far worse) are the source of test flakiness outside of the api being tested.\r\n *\r\n * This class can be used to create tests that do not require authentication, are synchronous,\r\n * are guaranteed to be self-contained (i.e. do not interfere with other tests running at the same time or later), and do not fail for reasons outside\r\n * of the control of the test itself. As a bonus, in addition to making tests more reliable, mocking IModelHub generally makes tests run *much* faster.\r\n *\r\n * On the other hand, tests that expect to find an existing iModels, checkpoints, changesets, etc. in IModelHub cannot be mocked. In that case, those tests\r\n * should be careful to NOT modify the data, since doing so causes interference with other tests running simultaneously. These tests should be limited to\r\n * low level testing of the core apis only.\r\n *\r\n * To initialize HubMock, call [[startup]] at the beginning of your test, usually in `describe.before`. Thereafter, all access to iModelHub for an iModel will be\r\n * directed to a [[LocalHub]] - your test code does not change. After the test(s) complete, call [[shutdown]] (usually in `describe.after`) to stop mocking IModelHub and clean\r\n * up any resources used by the test(s). If you want to mock a single test, call [[startup]] as the first line and [[shutdown]] as the last. If you wish to run the\r\n * test against a \"real\" IModelHub, you can simply comment off the call [[startup]], though in that case you should make sure the name of your\r\n * iModel is unique so your test won't collide with other tests (iModel name uniqueness is not necessary for mocked tests.)\r\n *\r\n * Mocked tests must always start by creating a new iModel via [[IModelHost[_hubAccess].createNewIModel]] with a `version0` iModel.\r\n * They use mock (aka \"bogus\") credentials for `AccessTokens`, which is fine since [[HubMock]] never accesses resources outside the current\r\n * computer.\r\n *\r\n * @note Only one HubMock at a time, *running in a single process*, may be active. The comments above about multiple simultaneous tests refer to tests\r\n * running on different computers, or on a single computer in multiple processes. All of those scenarios are problematic without mocking.\r\n *\r\n * @internal\r\n */\r\n/** Options for [[HubMock.startup]]. @internal */\r\nexport interface HubMockStartupOptions {\r\n /**\r\n * When `true`, every successful [[HubMock.pushChangeset]] call automatically uploads a V1 checkpoint\r\n * (the current briefcase `.bim` file) for the tip changeset index into [[LocalHub]].\r\n * This lets tests download a tip checkpoint and reverse changesets from it.\r\n */\r\n createTipCheckpointOnPush?: boolean;\r\n}\r\n\r\nexport class HubMock {\r\n private static mockRoot: LocalDirName | undefined;\r\n private static hubs = new Map<string, LocalHub>();\r\n private static _saveHubAccess: BackendHubAccess | undefined;\r\n private static _iTwinId: GuidString | undefined;\r\n private static _createTipCheckpointOnPush = false;\r\n\r\n /** Determine whether a test us currently being run under HubMock */\r\n public static get isValid() { return undefined !== this.mockRoot; }\r\n public static get iTwinId() {\r\n wasStarted(this._iTwinId);\r\n return this._iTwinId;\r\n }\r\n\r\n /**\r\n * Begin mocking IModelHub access. After this call, all access to IModelHub will be directed to a [[LocalHub]].\r\n * @param mockName a unique name (e.g. \"MyTest\") for this HubMock to disambiguate tests when more than one is simultaneously active.\r\n * It is used to create a private directory used by the HubMock for a test. That directory is removed when [[shutdown]] is called.\r\n */\r\n public static startup(mockName: LocalDirName, outputDir: string, options?: HubMockStartupOptions) {\r\n if (this.isValid)\r\n throw new Error(\"Either a previous test did not call HubMock.shutdown() properly, or more than one test is simultaneously attempting to use HubMock, which is not allowed\");\r\n\r\n this.hubs.clear();\r\n this.mockRoot = join(outputDir, \"HubMock\", mockName);\r\n IModelJsFs.recursiveMkDirSync(this.mockRoot);\r\n IModelJsFs.purgeDirSync(this.mockRoot);\r\n this._saveHubAccess = IModelHost[_getHubAccess]();\r\n\r\n IModelHost[_setHubAccess](this);\r\n HubMock._iTwinId = Guid.createValue(); // all iModels for this test get the same \"iTwinId\"\r\n this._createTipCheckpointOnPush = options?.createTipCheckpointOnPush ?? false;\r\n\r\n V2CheckpointManager[_mockCheckpoint] = mockCheckpoint;\r\n }\r\n\r\n /** Stop a HubMock that was previously started with [[startup]]\r\n * @note this function throws an exception if any of the iModels used during the tests are left open.\r\n */\r\n public static shutdown() {\r\n if (this.mockRoot === undefined)\r\n return;\r\n\r\n V2CheckpointManager[_mockCheckpoint] = undefined;\r\n this._createTipCheckpointOnPush = false;\r\n\r\n HubMock._iTwinId = undefined;\r\n for (const hub of this.hubs)\r\n hub[1].cleanup();\r\n\r\n this.hubs.clear();\r\n IModelJsFs.purgeDirSync(this.mockRoot);\r\n IModelJsFs.removeSync(this.mockRoot);\r\n IModelHost[_setHubAccess](this._saveHubAccess);\r\n this.mockRoot = undefined;\r\n }\r\n\r\n public static findLocalHub(iModelId: GuidString): LocalHub {\r\n const hub = this.hubs.get(iModelId);\r\n if (!hub)\r\n throw new Error(`local hub for iModel ${iModelId} not created`);\r\n return hub;\r\n }\r\n\r\n /** create a [[LocalHub]] for an iModel. */\r\n public static async createNewIModel(arg: CreateNewIModelProps): Promise<GuidString> {\r\n wasStarted(this.mockRoot);\r\n const props = { ...arg, iModelId: Guid.createValue() };\r\n const mock = new LocalHub(join(this.mockRoot, props.iModelId), props);\r\n this.hubs.set(props.iModelId, mock);\r\n return props.iModelId;\r\n }\r\n\r\n /** remove the [[LocalHub]] for an iModel */\r\n public static destroy(iModelId: GuidString) {\r\n this.findLocalHub(iModelId).cleanup();\r\n this.hubs.delete(iModelId);\r\n }\r\n\r\n /** All methods below are mocks of the [[BackendHubAccess]] interface */\r\n\r\n public static async getChangesetFromNamedVersion(arg: IModelIdArg & { versionName: string }): Promise<ChangesetProps> {\r\n return this.findLocalHub(arg.iModelId).findNamedVersion(arg.versionName);\r\n }\r\n\r\n private static changesetIndexFromArg(arg: ChangesetArg) {\r\n return (undefined !== arg.changeset.index) ? arg.changeset.index : this.findLocalHub(arg.iModelId).getChangesetIndex(arg.changeset.id);\r\n }\r\n\r\n public static async getChangesetFromVersion(arg: IModelIdArg & { version: IModelVersion }): Promise<ChangesetProps> {\r\n const hub = this.findLocalHub(arg.iModelId);\r\n const version = arg.version;\r\n if (version.isFirst)\r\n return hub.getChangesetByIndex(0);\r\n\r\n const asOf = version.getAsOfChangeSet();\r\n if (asOf)\r\n return hub.getChangesetById(asOf);\r\n\r\n const versionName = version.getName();\r\n if (versionName)\r\n return hub.findNamedVersion(versionName);\r\n\r\n return hub.getLatestChangeset();\r\n }\r\n\r\n public static async getLatestChangeset(arg: IModelIdArg): Promise<ChangesetProps> {\r\n return this.findLocalHub(arg.iModelId).getLatestChangeset();\r\n }\r\n\r\n private static async getAccessToken(arg: TokenArg) {\r\n return arg.accessToken ?? await IModelHost.getAccessToken();\r\n }\r\n\r\n public static async getMyBriefcaseIds(arg: IModelIdArg): Promise<number[]> {\r\n const accessToken = await this.getAccessToken(arg);\r\n return this.findLocalHub(arg.iModelId).getBriefcaseIds(accessToken);\r\n }\r\n\r\n public static async acquireNewBriefcaseId(arg: AcquireNewBriefcaseIdArg): Promise<number> {\r\n const accessToken = await this.getAccessToken(arg);\r\n return this.findLocalHub(arg.iModelId).acquireNewBriefcaseId(accessToken, arg.briefcaseAlias);\r\n }\r\n\r\n /** Release a briefcaseId. After this call it is illegal to generate changesets for the released briefcaseId. */\r\n public static async releaseBriefcase(arg: BriefcaseIdArg): Promise<void> {\r\n return this.findLocalHub(arg.iModelId).releaseBriefcaseId(arg.briefcaseId);\r\n }\r\n\r\n public static async downloadChangeset(arg: DownloadChangesetArg): Promise<ChangesetFileProps> {\r\n const changesetProps = this.findLocalHub(arg.iModelId).downloadChangeset({ index: this.changesetIndexFromArg(arg), targetDir: arg.targetDir });\r\n\r\n if (arg.progressCallback) {\r\n const totalSize = IModelJsFs.lstatSync(changesetProps.pathname)?.size;\r\n if (totalSize)\r\n await HubMock.mockProgressReporting(arg.progressCallback, totalSize);\r\n }\r\n\r\n return changesetProps;\r\n }\r\n\r\n public static async downloadChangesets(arg: DownloadChangesetRangeArg): Promise<ChangesetFileProps[]> {\r\n const changesetProps = this.findLocalHub(arg.iModelId).downloadChangesets({ range: arg.range, targetDir: arg.targetDir });\r\n\r\n if (arg.progressCallback) {\r\n const totalSize = changesetProps.reduce((sum, props) => sum + (IModelJsFs.lstatSync(props.pathname)?.size ?? 0), 0);\r\n await HubMock.mockProgressReporting(arg.progressCallback, totalSize);\r\n }\r\n\r\n return changesetProps;\r\n }\r\n\r\n public static async queryChangeset(arg: ChangesetArg): Promise<ChangesetProps> {\r\n return this.findLocalHub(arg.iModelId).getChangesetByIndex(this.changesetIndexFromArg(arg));\r\n }\r\n\r\n public static async queryChangesets(arg: IModelIdArg & { range?: ChangesetRange }): Promise<ChangesetProps[]> {\r\n return this.findLocalHub(arg.iModelId).queryChangesets(arg.range);\r\n }\r\n\r\n public static async pushChangeset(arg: IModelIdArg & { changesetProps: ChangesetFileProps }): Promise<ChangesetIndex> {\r\n const csIndex = this.findLocalHub(arg.iModelId).addChangeset(arg.changesetProps);\r\n if (this._createTipCheckpointOnPush)\r\n await this.createTipCheckpoint(arg.iModelId);\r\n return csIndex;\r\n }\r\n\r\n /**\r\n * Build and upload a V1 checkpoint at the current tip changeset of the given iModel.\r\n *\r\n * The checkpoint is constructed by copying the nearest prior checkpoint from [[LocalHub]] as a\r\n * starting base, then applying all subsequent changesets forward to the latest index via\r\n * [[BriefcaseManager.pullAndApplyChangesets]]. The result is registered in [[LocalHub]] so that\r\n * [[V2CheckpointManager]] (mock path) can serve it to consumers.\r\n *\r\n * When [[HubMockStartupOptions.createTipCheckpointOnPush]] is `true` this is called automatically\r\n * after every successful [[pushChangeset]]. Tests can also call it explicitly to create a single\r\n * checkpoint at the tip after all changesets have been pushed.\r\n */\r\n public static async createTipCheckpoint(iModelId: GuidString): Promise<void> {\r\n const hub = this.findLocalHub(iModelId);\r\n const csIndex = hub.latestChangesetIndex;\r\n // Find the nearest checkpoint that precedes the new tip and use it as the base.\r\n const prevIndex = hub.queryPreviousCheckpoint(csIndex);\r\n const prevCheckpointFile = join(hub.checkpointDir, hub.checkpointNameFromIndex(prevIndex));\r\n const tempFile = join(hub.rootDir, `checkpoint-building-${csIndex}.bim`);\r\n IModelJsFs.copySync(prevCheckpointFile, tempFile);\r\n try {\r\n const db = SnapshotDb.openForApplyChangesets(tempFile);\r\n try {\r\n await BriefcaseManager.pullAndApplyChangesets(db, { accessToken: \"\", toIndex: csIndex });\r\n db[_nativeDb].saveChanges();\r\n } finally {\r\n db.close();\r\n }\r\n\r\n hub.uploadCheckpoint({ changesetIndex: csIndex, localFile: tempFile });\r\n } finally {\r\n if (IModelJsFs.existsSync(tempFile))\r\n IModelJsFs.removeSync(tempFile);\r\n }\r\n }\r\n\r\n public static async queryV2Checkpoint(arg: CheckpointProps): Promise<V2CheckpointAccessProps | undefined> {\r\n return {\r\n accountName: \"none\",\r\n sasToken: \"none\",\r\n containerId: Guid.createValue(),\r\n dbName: `${arg.changeset.index ?? 0}.bim`,\r\n storageType: \"mock\",\r\n isMock: true,\r\n checkpoint: arg,\r\n } as V2CheckpointAccessProps;\r\n }\r\n\r\n public static async releaseAllLocks(arg: BriefcaseDbArg) {\r\n const hub = this.findLocalHub(arg.iModelId);\r\n hub.releaseAllLocks({ briefcaseId: arg.briefcaseId, changesetIndex: hub.getIndexFromChangeset(arg.changeset) });\r\n }\r\n\r\n public static async abandonAllLocks(arg: BriefcaseIdArg): Promise<void> {\r\n const hub = this.findLocalHub(arg.iModelId);\r\n hub.abandonAllLocks(arg);\r\n }\r\n\r\n public static async queryAllLocks(_arg: BriefcaseDbArg): Promise<LockProps[]> {\r\n return [];\r\n }\r\n\r\n public static async acquireLocks(arg: BriefcaseDbArg, locks: LockMap): Promise<void> {\r\n this.findLocalHub(arg.iModelId).acquireLocks(locks, arg);\r\n }\r\n\r\n public static async abandonLocks(arg: BriefcaseIdArg, locks: LockMap): Promise<void> {\r\n this.findLocalHub(arg.iModelId).abandonLocks(locks, arg);\r\n }\r\n\r\n public static async queryIModelByName(arg: IModelNameArg): Promise<GuidString | undefined> {\r\n for (const hub of this.hubs) {\r\n const localHub = hub[1];\r\n if (localHub.iTwinId === arg.iTwinId && localHub.iModelName === arg.iModelName)\r\n return localHub.iModelId;\r\n }\r\n return undefined;\r\n }\r\n\r\n public static async deleteIModel(arg: IModelIdArg & { iTwinId: GuidString }): Promise<void> {\r\n return this.destroy(arg.iModelId);\r\n }\r\n\r\n private static async mockProgressReporting(progressCallback: ProgressFunction, totalSize: number): Promise<void> {\r\n await new Promise((resolve, reject) => {\r\n let rejected = false;\r\n\r\n const mockProgress = (index: number) => {\r\n const bytesDownloaded = Math.floor(totalSize * (index / 4));\r\n if (!rejected && progressCallback(bytesDownloaded, totalSize) === ProgressStatus.Abort) {\r\n rejected = true;\r\n reject(new Error(\"AbortError\"));\r\n }\r\n };\r\n\r\n mockProgress(1);\r\n setTimeout(() => mockProgress(2), 50);\r\n setTimeout(() => mockProgress(3), 100);\r\n setTimeout(() => {\r\n mockProgress(4);\r\n resolve(undefined);\r\n }, 150);\r\n });\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaChangesetCanBeReversed.test.d.ts","sourceRoot":"","sources":["../../../src/test/SchemaChangesetCanBeReversed.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,239 @@
|
|
|
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 { DbResult, Guid } from "@itwin/core-bentley";
|
|
6
|
+
import { Code, IModel, IModelVersion, SubCategoryAppearance } from "@itwin/core-common";
|
|
7
|
+
import { assert } from "chai";
|
|
8
|
+
import { DrawingCategory } from "../Category";
|
|
9
|
+
import { HubMock } from "../internal/HubMock";
|
|
10
|
+
import { HubWrappers, IModelTestUtils } from "./IModelTestUtils";
|
|
11
|
+
import { KnownTestLocations } from "./KnownTestLocations";
|
|
12
|
+
import { TestUtils } from "./TestUtils";
|
|
13
|
+
import { withEditTxn } from "../EditTxn";
|
|
14
|
+
import { ChannelControl } from "../ChannelControl";
|
|
15
|
+
/**
|
|
16
|
+
* Schemas used to build a timeline with interleaved schema and data changes.
|
|
17
|
+
*
|
|
18
|
+
* v01.00.00 – base schema: classes A (base), C (extends A), D (extends A)
|
|
19
|
+
* v01.00.01 – adds PropC2 to class C (additive EC schema change)
|
|
20
|
+
* v01.00.02 – adds PropD2 to class D (additive EC schema change, on top of v01.00.01)
|
|
21
|
+
*/
|
|
22
|
+
const schemas = {
|
|
23
|
+
v01x00x00: `<?xml version="1.0" encoding="UTF-8"?>
|
|
24
|
+
<ECSchema schemaName="TestDomain" alias="td" version="01.00.00" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
|
|
25
|
+
<ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
|
|
26
|
+
<ECEntityClass typeName="A">
|
|
27
|
+
<BaseClass>bis:GraphicalElement2d</BaseClass>
|
|
28
|
+
<ECProperty propertyName="PropA" typeName="string"/>
|
|
29
|
+
</ECEntityClass>
|
|
30
|
+
<ECEntityClass typeName="C">
|
|
31
|
+
<BaseClass>A</BaseClass>
|
|
32
|
+
<ECProperty propertyName="PropC" typeName="string"/>
|
|
33
|
+
</ECEntityClass>
|
|
34
|
+
<ECEntityClass typeName="D">
|
|
35
|
+
<BaseClass>A</BaseClass>
|
|
36
|
+
<ECProperty propertyName="PropD" typeName="string"/>
|
|
37
|
+
</ECEntityClass>
|
|
38
|
+
</ECSchema>`,
|
|
39
|
+
v01x00x01AddPropC2: `<?xml version="1.0" encoding="UTF-8"?>
|
|
40
|
+
<ECSchema schemaName="TestDomain" alias="td" version="01.00.01" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
|
|
41
|
+
<ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
|
|
42
|
+
<ECEntityClass typeName="A">
|
|
43
|
+
<BaseClass>bis:GraphicalElement2d</BaseClass>
|
|
44
|
+
<ECProperty propertyName="PropA" typeName="string"/>
|
|
45
|
+
</ECEntityClass>
|
|
46
|
+
<ECEntityClass typeName="C">
|
|
47
|
+
<BaseClass>A</BaseClass>
|
|
48
|
+
<ECProperty propertyName="PropC" typeName="string"/>
|
|
49
|
+
<ECProperty propertyName="PropC2" typeName="string"/>
|
|
50
|
+
</ECEntityClass>
|
|
51
|
+
<ECEntityClass typeName="D">
|
|
52
|
+
<BaseClass>A</BaseClass>
|
|
53
|
+
<ECProperty propertyName="PropD" typeName="string"/>
|
|
54
|
+
</ECEntityClass>
|
|
55
|
+
</ECSchema>`,
|
|
56
|
+
v01x00x02AddPropD2: `<?xml version="1.0" encoding="UTF-8"?>
|
|
57
|
+
<ECSchema schemaName="TestDomain" alias="td" version="01.00.02" xmlns="http://www.bentley.com/schemas/Bentley.ECXML.3.2">
|
|
58
|
+
<ECSchemaReference name="BisCore" version="01.00.23" alias="bis"/>
|
|
59
|
+
<ECEntityClass typeName="A">
|
|
60
|
+
<BaseClass>bis:GraphicalElement2d</BaseClass>
|
|
61
|
+
<ECProperty propertyName="PropA" typeName="string"/>
|
|
62
|
+
</ECEntityClass>
|
|
63
|
+
<ECEntityClass typeName="C">
|
|
64
|
+
<BaseClass>A</BaseClass>
|
|
65
|
+
<ECProperty propertyName="PropC" typeName="string"/>
|
|
66
|
+
<ECProperty propertyName="PropC2" typeName="string"/>
|
|
67
|
+
</ECEntityClass>
|
|
68
|
+
<ECEntityClass typeName="D">
|
|
69
|
+
<BaseClass>A</BaseClass>
|
|
70
|
+
<ECProperty propertyName="PropD" typeName="string"/>
|
|
71
|
+
<ECProperty propertyName="PropD2" typeName="string"/>
|
|
72
|
+
</ECEntityClass>
|
|
73
|
+
</ECSchema>`,
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* Query whether a property exists on the given class via EC metadata (not DDL).
|
|
77
|
+
* Because schema-changeset reversal only rolls back EC-level mapping (not the backing SQLite columns),
|
|
78
|
+
* this is the correct layer to verify after a reversal.
|
|
79
|
+
*/
|
|
80
|
+
function hasECProperty(db, schemaName, className, propertyName) {
|
|
81
|
+
let found = false;
|
|
82
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
83
|
+
db.withPreparedStatement(`SELECT p.Name FROM ECDbMeta.ECPropertyDef p
|
|
84
|
+
JOIN ECDbMeta.ECClassDef c ON p.Class.Id = c.ECInstanceId
|
|
85
|
+
JOIN ECDbMeta.ECSchemaDef s ON c.Schema.Id = s.ECInstanceId
|
|
86
|
+
WHERE s.Name=:schema AND c.Name=:class AND p.Name=:prop`, (stmt) => {
|
|
87
|
+
stmt.bindString("schema", schemaName);
|
|
88
|
+
stmt.bindString("class", className);
|
|
89
|
+
stmt.bindString("prop", propertyName);
|
|
90
|
+
found = stmt.step() === DbResult.BE_SQLITE_ROW;
|
|
91
|
+
});
|
|
92
|
+
return found;
|
|
93
|
+
}
|
|
94
|
+
describe("SchemaChangesetCanBeReversed", () => {
|
|
95
|
+
let imodel;
|
|
96
|
+
let iModelId;
|
|
97
|
+
let drawingModelId;
|
|
98
|
+
let drawingCategoryId;
|
|
99
|
+
const createModelAndCategory = async (db) => {
|
|
100
|
+
const modelCode = IModelTestUtils.getUniqueModelCode(db, "DrawingModel");
|
|
101
|
+
await db.locks.acquireLocks({ shared: IModel.dictionaryId });
|
|
102
|
+
return withEditTxn(db, (txn) => {
|
|
103
|
+
const [, newModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(txn, modelCode);
|
|
104
|
+
const newCategoryId = DrawingCategory.insert(txn, IModel.dictionaryId, "DrawingCategory", new SubCategoryAppearance());
|
|
105
|
+
return [newModelId, newCategoryId];
|
|
106
|
+
});
|
|
107
|
+
};
|
|
108
|
+
const insertElement = (txn, className, properties) => {
|
|
109
|
+
const elementProps = {
|
|
110
|
+
classFullName: className,
|
|
111
|
+
model: drawingModelId,
|
|
112
|
+
category: drawingCategoryId,
|
|
113
|
+
code: Code.createEmpty(),
|
|
114
|
+
...properties,
|
|
115
|
+
};
|
|
116
|
+
const element = txn.iModel.elements.createElement(elementProps);
|
|
117
|
+
txn.insertElement(element.toJSON());
|
|
118
|
+
};
|
|
119
|
+
before(async () => {
|
|
120
|
+
HubMock.startup("SchemaChangesetCanBeReversed", KnownTestLocations.outputDir);
|
|
121
|
+
await TestUtils.shutdownBackend();
|
|
122
|
+
await TestUtils.startBackend();
|
|
123
|
+
});
|
|
124
|
+
beforeEach(async () => {
|
|
125
|
+
iModelId = await HubWrappers.createIModel("user1", HubMock.iTwinId, `Test-${Guid.createValue()}`);
|
|
126
|
+
imodel = await HubWrappers.downloadAndOpenBriefcase({ accessToken: "user1", iTwinId: HubMock.iTwinId, iModelId });
|
|
127
|
+
imodel.channels.addAllowedChannel(ChannelControl.sharedChannelName);
|
|
128
|
+
[drawingModelId, drawingCategoryId] = await createModelAndCategory(imodel);
|
|
129
|
+
});
|
|
130
|
+
afterEach(async () => {
|
|
131
|
+
imodel.close();
|
|
132
|
+
await HubMock.deleteIModel({ accessToken: "user1", iTwinId: HubMock.iTwinId, iModelId });
|
|
133
|
+
});
|
|
134
|
+
after(async () => {
|
|
135
|
+
HubMock.shutdown();
|
|
136
|
+
await TestUtils.shutdownBackend();
|
|
137
|
+
await TestUtils.startBackend();
|
|
138
|
+
});
|
|
139
|
+
/**
|
|
140
|
+
* Builds a timeline with interleaved schema and data changesets:
|
|
141
|
+
*
|
|
142
|
+
* CS1 – setup (model, category) + import schema v01.00.00
|
|
143
|
+
* CS2 – insert two elements of class C (data)
|
|
144
|
+
* CS3 – import schema v01.00.01 adding PropC2 to C (schema)
|
|
145
|
+
* CS4 – insert two elements of class C with PropC2 (data)
|
|
146
|
+
* CS5 – import schema v01.00.02 adding PropD2 to D (schema)
|
|
147
|
+
* CS6 – insert two elements of class D with PropD2 (data)
|
|
148
|
+
*
|
|
149
|
+
* After all six changesets are pushed a single V1 checkpoint is built at the tip
|
|
150
|
+
* (CS6) via [[HubMock.createTipCheckpoint]]. The test then calls
|
|
151
|
+
* [[HubWrappers.downloadAndOpenCheckpoint]] at three older versions (CS5, CS3, CS1).
|
|
152
|
+
*
|
|
153
|
+
* For each request [[V2CheckpointManager]] (mock path) copies the tip checkpoint — the
|
|
154
|
+
* *nearest* available checkpoint — to the local target file. [[CheckpointManager.updateToRequestedVersion]]
|
|
155
|
+
* detects that the downloaded file is at a newer changeset than requested and calls
|
|
156
|
+
* [[BriefcaseManager.pullAndApplyChangesets]] with `toIndex < currentIndex`, which reverses
|
|
157
|
+
* the needed changesets in order. The opened snapshot is therefore at the exact requested
|
|
158
|
+
* version and its EC schema metadata reflects the pre-reversal state.
|
|
159
|
+
*/
|
|
160
|
+
it("should open checkpoint at older schema version by reversing from the tip checkpoint", async () => {
|
|
161
|
+
// ── CS1: model/category setup + base schema ──────────────────────────────
|
|
162
|
+
await imodel.importSchemaStrings([schemas.v01x00x00]);
|
|
163
|
+
await imodel.pushChanges({ description: "CS1: setup and import base schema v01.00.00" });
|
|
164
|
+
const cs1Id = imodel.changeset.id;
|
|
165
|
+
// ── CS2: insert C elements (data only) ───────────────────────────────────
|
|
166
|
+
await imodel.locks.acquireLocks({ shared: drawingModelId });
|
|
167
|
+
withEditTxn(imodel, (txn) => {
|
|
168
|
+
insertElement(txn, "TestDomain:C", { propC: "c_val_1" });
|
|
169
|
+
insertElement(txn, "TestDomain:C", { propC: "c_val_2" });
|
|
170
|
+
});
|
|
171
|
+
await imodel.pushChanges({ description: "CS2: insert C elements" });
|
|
172
|
+
// ── CS3: schema v01.00.01 – adds PropC2 to C ─────────────────────────────
|
|
173
|
+
await imodel.importSchemaStrings([schemas.v01x00x01AddPropC2]);
|
|
174
|
+
await imodel.pushChanges({ description: "CS3: import schema v01.00.01 (adds PropC2)" });
|
|
175
|
+
const cs3Id = imodel.changeset.id;
|
|
176
|
+
// ── CS4: insert more C elements using PropC2 (data only) ─────────────────
|
|
177
|
+
await imodel.locks.acquireLocks({ shared: drawingModelId });
|
|
178
|
+
withEditTxn(imodel, (txn) => {
|
|
179
|
+
insertElement(txn, "TestDomain:C", { propC: "c_val_3", propC2: "c2_val_3" });
|
|
180
|
+
insertElement(txn, "TestDomain:C", { propC: "c_val_4", propC2: "c2_val_4" });
|
|
181
|
+
});
|
|
182
|
+
await imodel.pushChanges({ description: "CS4: insert C elements with PropC2" });
|
|
183
|
+
// ── CS5: schema v01.00.02 – adds PropD2 to D ─────────────────────────────
|
|
184
|
+
await imodel.importSchemaStrings([schemas.v01x00x02AddPropD2]);
|
|
185
|
+
await imodel.pushChanges({ description: "CS5: import schema v01.00.02 (adds PropD2)" });
|
|
186
|
+
const cs5Id = imodel.changeset.id;
|
|
187
|
+
// ── CS6: insert D elements using PropD2 (data only) ──────────────────────
|
|
188
|
+
await imodel.locks.acquireLocks({ shared: drawingModelId });
|
|
189
|
+
withEditTxn(imodel, (txn) => {
|
|
190
|
+
insertElement(txn, "TestDomain:D", { propD: "d_val_5", propD2: "d2_val_5" });
|
|
191
|
+
insertElement(txn, "TestDomain:D", { propD: "d_val_6", propD2: "d2_val_6" });
|
|
192
|
+
});
|
|
193
|
+
await imodel.pushChanges({ description: "CS6: insert D elements with PropD2" });
|
|
194
|
+
// ── Build a single V1 checkpoint at the tip (CS6) ────────────────────────
|
|
195
|
+
// All three verify steps below will download this tip checkpoint and reverse
|
|
196
|
+
// it to the requested version via BriefcaseManager.pullAndApplyChangesets.
|
|
197
|
+
await HubMock.createTipCheckpoint(iModelId);
|
|
198
|
+
// ── Open at CS5 (schema v01.00.02): reverses CS6 (data) ──────────────────
|
|
199
|
+
{
|
|
200
|
+
const snap = await HubWrappers.downloadAndOpenCheckpoint({
|
|
201
|
+
accessToken: "user1",
|
|
202
|
+
iTwinId: HubMock.iTwinId,
|
|
203
|
+
iModelId,
|
|
204
|
+
asOf: IModelVersion.asOfChangeSet(cs5Id).toJSON(),
|
|
205
|
+
});
|
|
206
|
+
assert.equal(snap.querySchemaVersion("TestDomain"), "1.0.2", "schema is v01.00.02 at CS5");
|
|
207
|
+
assert.isTrue(hasECProperty(snap, "TestDomain", "C", "PropC2"), "PropC2 present at CS5");
|
|
208
|
+
assert.isTrue(hasECProperty(snap, "TestDomain", "D", "PropD2"), "PropD2 present at CS5");
|
|
209
|
+
snap.close();
|
|
210
|
+
}
|
|
211
|
+
// ── Open at CS3 (schema v01.00.01): reverses CS4 (data) + CS5 (schema) + CS6 (data) ──
|
|
212
|
+
{
|
|
213
|
+
const snap = await HubWrappers.downloadAndOpenCheckpoint({
|
|
214
|
+
accessToken: "user1",
|
|
215
|
+
iTwinId: HubMock.iTwinId,
|
|
216
|
+
iModelId,
|
|
217
|
+
asOf: IModelVersion.asOfChangeSet(cs3Id).toJSON(),
|
|
218
|
+
});
|
|
219
|
+
assert.equal(snap.querySchemaVersion("TestDomain"), "1.0.1", "schema is v01.00.01 at CS3");
|
|
220
|
+
assert.isTrue(hasECProperty(snap, "TestDomain", "C", "PropC2"), "PropC2 present at CS3");
|
|
221
|
+
assert.isFalse(hasECProperty(snap, "TestDomain", "D", "PropD2"), "PropD2 absent at CS3 (CS5 schema reverted)");
|
|
222
|
+
snap.close();
|
|
223
|
+
}
|
|
224
|
+
// ── Open at CS1 (schema v01.00.00): reverses CS2 through CS6 ─────────────
|
|
225
|
+
{
|
|
226
|
+
const snap = await HubWrappers.downloadAndOpenCheckpoint({
|
|
227
|
+
accessToken: "user1",
|
|
228
|
+
iTwinId: HubMock.iTwinId,
|
|
229
|
+
iModelId,
|
|
230
|
+
asOf: IModelVersion.asOfChangeSet(cs1Id).toJSON(),
|
|
231
|
+
});
|
|
232
|
+
assert.equal(snap.querySchemaVersion("TestDomain"), "1.0.0", "schema is v01.00.00 at CS1");
|
|
233
|
+
assert.isFalse(hasECProperty(snap, "TestDomain", "C", "PropC2"), "PropC2 absent at CS1 (CS3 schema reverted)");
|
|
234
|
+
assert.isFalse(hasECProperty(snap, "TestDomain", "D", "PropD2"), "PropD2 absent at CS1");
|
|
235
|
+
snap.close();
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
//# sourceMappingURL=SchemaChangesetCanBeReversed.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SchemaChangesetCanBeReversed.test.js","sourceRoot":"","sources":["../../../src/test/SchemaChangesetCanBeReversed.test.ts"],"names":[],"mappings":"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","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\n\r\nimport { DbResult, Guid } from \"@itwin/core-bentley\";\r\nimport { Code, GeometricElementProps, IModel, IModelVersion, SubCategoryAppearance } from \"@itwin/core-common\";\r\nimport { assert } from \"chai\";\r\nimport { DrawingCategory } from \"../Category\";\r\nimport { BriefcaseDb, IModelDb } from \"../IModelDb\";\r\nimport { HubMock } from \"../internal/HubMock\";\r\nimport { HubWrappers, IModelTestUtils } from \"./IModelTestUtils\";\r\nimport { KnownTestLocations } from \"./KnownTestLocations\";\r\nimport { TestUtils } from \"./TestUtils\";\r\nimport { EditTxn, withEditTxn } from \"../EditTxn\";\r\nimport { ChannelControl } from \"../ChannelControl\";\r\n\r\n/**\r\n * Schemas used to build a timeline with interleaved schema and data changes.\r\n *\r\n * v01.00.00 – base schema: classes A (base), C (extends A), D (extends A)\r\n * v01.00.01 – adds PropC2 to class C (additive EC schema change)\r\n * v01.00.02 – adds PropD2 to class D (additive EC schema change, on top of v01.00.01)\r\n */\r\nconst schemas = {\r\n v01x00x00: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <ECSchema schemaName=\"TestDomain\" alias=\"td\" version=\"01.00.00\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.3.2\">\r\n <ECSchemaReference name=\"BisCore\" version=\"01.00.23\" alias=\"bis\"/>\r\n <ECEntityClass typeName=\"A\">\r\n <BaseClass>bis:GraphicalElement2d</BaseClass>\r\n <ECProperty propertyName=\"PropA\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n <ECEntityClass typeName=\"C\">\r\n <BaseClass>A</BaseClass>\r\n <ECProperty propertyName=\"PropC\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n <ECEntityClass typeName=\"D\">\r\n <BaseClass>A</BaseClass>\r\n <ECProperty propertyName=\"PropD\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n </ECSchema>`,\r\n\r\n v01x00x01AddPropC2: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <ECSchema schemaName=\"TestDomain\" alias=\"td\" version=\"01.00.01\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.3.2\">\r\n <ECSchemaReference name=\"BisCore\" version=\"01.00.23\" alias=\"bis\"/>\r\n <ECEntityClass typeName=\"A\">\r\n <BaseClass>bis:GraphicalElement2d</BaseClass>\r\n <ECProperty propertyName=\"PropA\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n <ECEntityClass typeName=\"C\">\r\n <BaseClass>A</BaseClass>\r\n <ECProperty propertyName=\"PropC\" typeName=\"string\"/>\r\n <ECProperty propertyName=\"PropC2\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n <ECEntityClass typeName=\"D\">\r\n <BaseClass>A</BaseClass>\r\n <ECProperty propertyName=\"PropD\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n </ECSchema>`,\r\n\r\n v01x00x02AddPropD2: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\r\n <ECSchema schemaName=\"TestDomain\" alias=\"td\" version=\"01.00.02\" xmlns=\"http://www.bentley.com/schemas/Bentley.ECXML.3.2\">\r\n <ECSchemaReference name=\"BisCore\" version=\"01.00.23\" alias=\"bis\"/>\r\n <ECEntityClass typeName=\"A\">\r\n <BaseClass>bis:GraphicalElement2d</BaseClass>\r\n <ECProperty propertyName=\"PropA\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n <ECEntityClass typeName=\"C\">\r\n <BaseClass>A</BaseClass>\r\n <ECProperty propertyName=\"PropC\" typeName=\"string\"/>\r\n <ECProperty propertyName=\"PropC2\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n <ECEntityClass typeName=\"D\">\r\n <BaseClass>A</BaseClass>\r\n <ECProperty propertyName=\"PropD\" typeName=\"string\"/>\r\n <ECProperty propertyName=\"PropD2\" typeName=\"string\"/>\r\n </ECEntityClass>\r\n </ECSchema>`,\r\n};\r\n\r\n/**\r\n * Query whether a property exists on the given class via EC metadata (not DDL).\r\n * Because schema-changeset reversal only rolls back EC-level mapping (not the backing SQLite columns),\r\n * this is the correct layer to verify after a reversal.\r\n */\r\nfunction hasECProperty(db: IModelDb, schemaName: string, className: string, propertyName: string): boolean {\r\n let found = false;\r\n // eslint-disable-next-line @typescript-eslint/no-deprecated\r\n db.withPreparedStatement(\r\n `SELECT p.Name FROM ECDbMeta.ECPropertyDef p\r\n JOIN ECDbMeta.ECClassDef c ON p.Class.Id = c.ECInstanceId\r\n JOIN ECDbMeta.ECSchemaDef s ON c.Schema.Id = s.ECInstanceId\r\n WHERE s.Name=:schema AND c.Name=:class AND p.Name=:prop`,\r\n (stmt) => {\r\n stmt.bindString(\"schema\", schemaName);\r\n stmt.bindString(\"class\", className);\r\n stmt.bindString(\"prop\", propertyName);\r\n found = stmt.step() === DbResult.BE_SQLITE_ROW;\r\n }\r\n );\r\n return found;\r\n}\r\n\r\ndescribe(\"SchemaChangesetCanBeReversed\", () => {\r\n let imodel: BriefcaseDb;\r\n let iModelId: string;\r\n let drawingModelId: string;\r\n let drawingCategoryId: string;\r\n\r\n const createModelAndCategory = async (db: BriefcaseDb) => {\r\n const modelCode = IModelTestUtils.getUniqueModelCode(db, \"DrawingModel\");\r\n await db.locks.acquireLocks({ shared: IModel.dictionaryId });\r\n return withEditTxn(db, (txn) => {\r\n const [, newModelId] = IModelTestUtils.createAndInsertDrawingPartitionAndModel(txn, modelCode);\r\n const newCategoryId = DrawingCategory.insert(txn, IModel.dictionaryId, \"DrawingCategory\", new SubCategoryAppearance());\r\n return [newModelId, newCategoryId] as const;\r\n });\r\n };\r\n\r\n const insertElement = (txn: EditTxn, className: string, properties: Record<string, unknown>): void => {\r\n const elementProps: GeometricElementProps = {\r\n classFullName: className,\r\n model: drawingModelId,\r\n category: drawingCategoryId,\r\n code: Code.createEmpty(),\r\n ...properties,\r\n };\r\n const element = txn.iModel.elements.createElement(elementProps);\r\n txn.insertElement(element.toJSON());\r\n };\r\n\r\n before(async () => {\r\n HubMock.startup(\"SchemaChangesetCanBeReversed\", KnownTestLocations.outputDir);\r\n await TestUtils.shutdownBackend();\r\n await TestUtils.startBackend();\r\n });\r\n\r\n beforeEach(async () => {\r\n iModelId = await HubWrappers.createIModel(\"user1\", HubMock.iTwinId, `Test-${Guid.createValue()}`);\r\n imodel = await HubWrappers.downloadAndOpenBriefcase({ accessToken: \"user1\", iTwinId: HubMock.iTwinId, iModelId });\r\n imodel.channels.addAllowedChannel(ChannelControl.sharedChannelName);\r\n [drawingModelId, drawingCategoryId] = await createModelAndCategory(imodel);\r\n });\r\n\r\n afterEach(async () => {\r\n imodel.close();\r\n await HubMock.deleteIModel({ accessToken: \"user1\", iTwinId: HubMock.iTwinId, iModelId });\r\n });\r\n\r\n after(async () => {\r\n HubMock.shutdown();\r\n await TestUtils.shutdownBackend();\r\n await TestUtils.startBackend();\r\n });\r\n\r\n /**\r\n * Builds a timeline with interleaved schema and data changesets:\r\n *\r\n * CS1 – setup (model, category) + import schema v01.00.00\r\n * CS2 – insert two elements of class C (data)\r\n * CS3 – import schema v01.00.01 adding PropC2 to C (schema)\r\n * CS4 – insert two elements of class C with PropC2 (data)\r\n * CS5 – import schema v01.00.02 adding PropD2 to D (schema)\r\n * CS6 – insert two elements of class D with PropD2 (data)\r\n *\r\n * After all six changesets are pushed a single V1 checkpoint is built at the tip\r\n * (CS6) via [[HubMock.createTipCheckpoint]]. The test then calls\r\n * [[HubWrappers.downloadAndOpenCheckpoint]] at three older versions (CS5, CS3, CS1).\r\n *\r\n * For each request [[V2CheckpointManager]] (mock path) copies the tip checkpoint — the\r\n * *nearest* available checkpoint — to the local target file. [[CheckpointManager.updateToRequestedVersion]]\r\n * detects that the downloaded file is at a newer changeset than requested and calls\r\n * [[BriefcaseManager.pullAndApplyChangesets]] with `toIndex < currentIndex`, which reverses\r\n * the needed changesets in order. The opened snapshot is therefore at the exact requested\r\n * version and its EC schema metadata reflects the pre-reversal state.\r\n */\r\n it(\"should open checkpoint at older schema version by reversing from the tip checkpoint\", async () => {\r\n // ── CS1: model/category setup + base schema ──────────────────────────────\r\n await imodel.importSchemaStrings([schemas.v01x00x00]);\r\n await imodel.pushChanges({ description: \"CS1: setup and import base schema v01.00.00\" });\r\n const cs1Id = imodel.changeset.id;\r\n\r\n // ── CS2: insert C elements (data only) ───────────────────────────────────\r\n await imodel.locks.acquireLocks({ shared: drawingModelId });\r\n withEditTxn(imodel, (txn) => {\r\n insertElement(txn, \"TestDomain:C\", { propC: \"c_val_1\" });\r\n insertElement(txn, \"TestDomain:C\", { propC: \"c_val_2\" });\r\n });\r\n await imodel.pushChanges({ description: \"CS2: insert C elements\" });\r\n\r\n // ── CS3: schema v01.00.01 – adds PropC2 to C ─────────────────────────────\r\n await imodel.importSchemaStrings([schemas.v01x00x01AddPropC2]);\r\n await imodel.pushChanges({ description: \"CS3: import schema v01.00.01 (adds PropC2)\" });\r\n const cs3Id = imodel.changeset.id;\r\n\r\n // ── CS4: insert more C elements using PropC2 (data only) ─────────────────\r\n await imodel.locks.acquireLocks({ shared: drawingModelId });\r\n withEditTxn(imodel, (txn) => {\r\n insertElement(txn, \"TestDomain:C\", { propC: \"c_val_3\", propC2: \"c2_val_3\" });\r\n insertElement(txn, \"TestDomain:C\", { propC: \"c_val_4\", propC2: \"c2_val_4\" });\r\n });\r\n await imodel.pushChanges({ description: \"CS4: insert C elements with PropC2\" });\r\n\r\n // ── CS5: schema v01.00.02 – adds PropD2 to D ─────────────────────────────\r\n await imodel.importSchemaStrings([schemas.v01x00x02AddPropD2]);\r\n await imodel.pushChanges({ description: \"CS5: import schema v01.00.02 (adds PropD2)\" });\r\n const cs5Id = imodel.changeset.id;\r\n\r\n // ── CS6: insert D elements using PropD2 (data only) ──────────────────────\r\n await imodel.locks.acquireLocks({ shared: drawingModelId });\r\n withEditTxn(imodel, (txn) => {\r\n insertElement(txn, \"TestDomain:D\", { propD: \"d_val_5\", propD2: \"d2_val_5\" });\r\n insertElement(txn, \"TestDomain:D\", { propD: \"d_val_6\", propD2: \"d2_val_6\" });\r\n });\r\n await imodel.pushChanges({ description: \"CS6: insert D elements with PropD2\" });\r\n\r\n // ── Build a single V1 checkpoint at the tip (CS6) ────────────────────────\r\n // All three verify steps below will download this tip checkpoint and reverse\r\n // it to the requested version via BriefcaseManager.pullAndApplyChangesets.\r\n await HubMock.createTipCheckpoint(iModelId);\r\n\r\n // ── Open at CS5 (schema v01.00.02): reverses CS6 (data) ──────────────────\r\n {\r\n const snap = await HubWrappers.downloadAndOpenCheckpoint({\r\n accessToken: \"user1\",\r\n iTwinId: HubMock.iTwinId,\r\n iModelId,\r\n asOf: IModelVersion.asOfChangeSet(cs5Id).toJSON(),\r\n });\r\n assert.equal(snap.querySchemaVersion(\"TestDomain\"), \"1.0.2\", \"schema is v01.00.02 at CS5\");\r\n assert.isTrue(hasECProperty(snap, \"TestDomain\", \"C\", \"PropC2\"), \"PropC2 present at CS5\");\r\n assert.isTrue(hasECProperty(snap, \"TestDomain\", \"D\", \"PropD2\"), \"PropD2 present at CS5\");\r\n snap.close();\r\n }\r\n\r\n // ── Open at CS3 (schema v01.00.01): reverses CS4 (data) + CS5 (schema) + CS6 (data) ──\r\n {\r\n const snap = await HubWrappers.downloadAndOpenCheckpoint({\r\n accessToken: \"user1\",\r\n iTwinId: HubMock.iTwinId,\r\n iModelId,\r\n asOf: IModelVersion.asOfChangeSet(cs3Id).toJSON(),\r\n });\r\n assert.equal(snap.querySchemaVersion(\"TestDomain\"), \"1.0.1\", \"schema is v01.00.01 at CS3\");\r\n assert.isTrue(hasECProperty(snap, \"TestDomain\", \"C\", \"PropC2\"), \"PropC2 present at CS3\");\r\n assert.isFalse(hasECProperty(snap, \"TestDomain\", \"D\", \"PropD2\"), \"PropD2 absent at CS3 (CS5 schema reverted)\");\r\n snap.close();\r\n }\r\n\r\n // ── Open at CS1 (schema v01.00.00): reverses CS2 through CS6 ─────────────\r\n {\r\n const snap = await HubWrappers.downloadAndOpenCheckpoint({\r\n accessToken: \"user1\",\r\n iTwinId: HubMock.iTwinId,\r\n iModelId,\r\n asOf: IModelVersion.asOfChangeSet(cs1Id).toJSON(),\r\n });\r\n assert.equal(snap.querySchemaVersion(\"TestDomain\"), \"1.0.0\", \"schema is v01.00.00 at CS1\");\r\n assert.isFalse(hasECProperty(snap, \"TestDomain\", \"C\", \"PropC2\"), \"PropC2 absent at CS1 (CS3 schema reverted)\");\r\n assert.isFalse(hasECProperty(snap, \"TestDomain\", \"D\", \"PropD2\"), \"PropD2 absent at CS1\");\r\n snap.close();\r\n }\r\n });\r\n});\r\n"]}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* See LICENSE.md in the project root for license terms and full copyright notice.
|
|
4
4
|
*--------------------------------------------------------------------------------------------*/
|
|
5
5
|
import { expect } from "chai";
|
|
6
|
-
import { Geometry, Point3d, Range2d, Transform, Vector3d } from "@itwin/core-geometry";
|
|
6
|
+
import { Geometry, Path, Point3d, Range2d, Transform, Vector3d } from "@itwin/core-geometry";
|
|
7
7
|
import { ColorDef, GeometryParams, textAnnotationFrameShapes } from "@itwin/core-common";
|
|
8
8
|
import { appendFrameToBuilder, computeFrame } from "../../annotations/FrameGeometry";
|
|
9
9
|
import { Id64 } from "@itwin/core-bentley";
|
|
@@ -39,6 +39,7 @@ describe("FrameGeometry", () => {
|
|
|
39
39
|
const result = appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);
|
|
40
40
|
expect(result).to.be.true;
|
|
41
41
|
expect(builder.geometries.length).to.be.equal(2);
|
|
42
|
+
expect(builder.geometries[1] instanceof Path).to.be.true; // The second geometry should be the outline geometry, which is a Path
|
|
42
43
|
});
|
|
43
44
|
it("should set fill and border colors from frame", () => {
|
|
44
45
|
const builder = new MockBuilder();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FrameGeometry.test.js","sourceRoot":"","sources":["../../../../src/test/annotations/FrameGeometry.test.ts"],"names":[],"mappings":"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","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\n\r\nimport { expect } from \"chai\";\r\nimport { CurvePrimitive, Geometry, Point3d, Range2d, Transform, Vector3d } from \"@itwin/core-geometry\";\r\nimport { ColorDef, GeometryParams, textAnnotationFrameShapes, TextFrameStyleProps } from \"@itwin/core-common\";\r\nimport { appendFrameToBuilder, computeFrame } from \"../../annotations/FrameGeometry\";\r\nimport { Id64 } from \"@itwin/core-bentley\";\r\nimport { MockBuilder } from \"../AnnotationTestUtils\";\r\n\r\nfunction isContinuous(geometries: CurvePrimitive[]): boolean {\r\n return geometries.every((current, index) => {\r\n // If the index is 0, get the last geometry in the list to see if they connect and form a loop\r\n const previous = (index === 0) ? geometries[geometries.length - 1] : geometries[index - 1];\r\n\r\n return previous.endPoint().isAlmostEqual(current.startPoint(), Geometry.smallMetricDistance);\r\n });\r\n}\r\n\r\ndescribe(\"FrameGeometry\", () => {\r\n const defaultRange = Range2d.createXYXY(0, 0, 10, 20);\r\n const defaultTransform = Transform.createIdentity();\r\n const defaultParams = new GeometryParams(Id64.invalid);\r\n\r\n describe(\"appendFrameToBuilder\", () => {\r\n it(\"should not append frame if shape is undefined or 'none'\", () => {\r\n const builder = new MockBuilder();\r\n expect(appendFrameToBuilder(builder, { shape: undefined }, defaultRange, defaultTransform, defaultParams)).to.be.false;\r\n expect(appendFrameToBuilder(builder, { shape: \"none\" }, defaultRange, defaultTransform, defaultParams)).to.be.false;\r\n expect(appendFrameToBuilder(builder, { shape: \"none\", fillColor: ColorDef.green.toJSON() }, defaultRange, defaultTransform, defaultParams)).to.be.false;\r\n });\r\n\r\n it(\"should append only a frame\", () => {\r\n const builder = new MockBuilder();\r\n const frame: TextFrameStyleProps = { shape: \"rectangle\" };\r\n const result = appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);\r\n expect(result).to.be.true;\r\n expect(builder.geometries.length).to.be.equal(1);\r\n });\r\n\r\n it(\"should append a frame and fill\", () => {\r\n const builder = new MockBuilder();\r\n const frame: TextFrameStyleProps = { shape: \"rectangle\", fillColor: ColorDef.green.toJSON() };\r\n const result = appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);\r\n expect(result).to.be.true;\r\n expect(builder.geometries.length).to.be.equal(2);\r\n });\r\n\r\n it(\"should set fill and border colors from frame\", () => {\r\n const builder = new MockBuilder();\r\n const frame: TextFrameStyleProps = {\r\n shape: \"rectangle\",\r\n fillColor: ColorDef.blue.toJSON(),\r\n borderColor: ColorDef.red.toJSON(),\r\n borderWeight: 3,\r\n };\r\n appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);\r\n const params = builder.params[builder.params.length - 1];\r\n expect(params.fillColor?.tbgr).to.equal(ColorDef.blue.tbgr);\r\n expect(params.lineColor?.tbgr).to.equal(ColorDef.red.tbgr);\r\n expect(params.weight).to.equal(3);\r\n });\r\n\r\n });\r\n describe(\"computeGeometry\", () => {\r\n const shapes = textAnnotationFrameShapes.filter(shape => shape !== \"none\");\r\n it(\"should compute different frame shapes and they should be continuous\", () => {\r\n for (const shape of shapes) {\r\n const frame = computeFrame({ frame: shape, range: defaultRange, transform: defaultTransform });\r\n expect(frame).to.exist;\r\n\r\n const curvePrimitives = frame.collectCurvePrimitives(undefined, true);\r\n\r\n if (curvePrimitives.length > 1) {\r\n // The start point of a given segment should be the end point of the previous segment\r\n const isContinuousShape = isContinuous(frame.collectCurvePrimitives(undefined, true))\r\n expect(isContinuousShape, `Frame shape ${shape} should be continuous`).to.be.true;\r\n }\r\n }\r\n });\r\n\r\n it(\"should apply transform\", () => {\r\n const origin = Point3d.create(5, 6, 7);\r\n const vector = Vector3d.create(1, 2, 3);\r\n vector.tryNormalizeInPlace();\r\n const transform = Transform.createRigidFromOriginAndVector(origin, vector)!; // This transform is something I made up for this test. It should exist.\r\n\r\n for (const shape of shapes) {\r\n const rotatedFrame = computeFrame({ frame: shape, range: defaultRange, transform });\r\n const unRotatedFrame = computeFrame({ frame: shape, range: defaultRange, transform: defaultTransform });\r\n\r\n const control = unRotatedFrame.cloneTransformed(transform)!; // This transform is something I made up for this test. It should exist.\r\n expect(rotatedFrame.isAlmostEqual(control), `Rotated frame for shape ${shape} should match control`).to.be.true;\r\n }\r\n });\r\n });\r\n});\r\n"]}
|
|
1
|
+
{"version":3,"file":"FrameGeometry.test.js","sourceRoot":"","sources":["../../../../src/test/annotations/FrameGeometry.test.ts"],"names":[],"mappings":"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","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\n\r\nimport { expect } from \"chai\";\r\nimport { CurvePrimitive, Geometry, Path, Point3d, Range2d, Transform, Vector3d } from \"@itwin/core-geometry\";\r\nimport { ColorDef, GeometryParams, textAnnotationFrameShapes, TextFrameStyleProps } from \"@itwin/core-common\";\r\nimport { appendFrameToBuilder, computeFrame } from \"../../annotations/FrameGeometry\";\r\nimport { Id64 } from \"@itwin/core-bentley\";\r\nimport { MockBuilder } from \"../AnnotationTestUtils\";\r\n\r\nfunction isContinuous(geometries: CurvePrimitive[]): boolean {\r\n return geometries.every((current, index) => {\r\n // If the index is 0, get the last geometry in the list to see if they connect and form a loop\r\n const previous = (index === 0) ? geometries[geometries.length - 1] : geometries[index - 1];\r\n\r\n return previous.endPoint().isAlmostEqual(current.startPoint(), Geometry.smallMetricDistance);\r\n });\r\n}\r\n\r\ndescribe(\"FrameGeometry\", () => {\r\n const defaultRange = Range2d.createXYXY(0, 0, 10, 20);\r\n const defaultTransform = Transform.createIdentity();\r\n const defaultParams = new GeometryParams(Id64.invalid);\r\n\r\n describe(\"appendFrameToBuilder\", () => {\r\n it(\"should not append frame if shape is undefined or 'none'\", () => {\r\n const builder = new MockBuilder();\r\n expect(appendFrameToBuilder(builder, { shape: undefined }, defaultRange, defaultTransform, defaultParams)).to.be.false;\r\n expect(appendFrameToBuilder(builder, { shape: \"none\" }, defaultRange, defaultTransform, defaultParams)).to.be.false;\r\n expect(appendFrameToBuilder(builder, { shape: \"none\", fillColor: ColorDef.green.toJSON() }, defaultRange, defaultTransform, defaultParams)).to.be.false;\r\n });\r\n\r\n it(\"should append only a frame\", () => {\r\n const builder = new MockBuilder();\r\n const frame: TextFrameStyleProps = { shape: \"rectangle\" };\r\n const result = appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);\r\n expect(result).to.be.true;\r\n expect(builder.geometries.length).to.be.equal(1);\r\n });\r\n\r\n it(\"should append a frame and fill\", () => {\r\n const builder = new MockBuilder();\r\n const frame: TextFrameStyleProps = { shape: \"rectangle\", fillColor: ColorDef.green.toJSON() };\r\n const result = appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);\r\n expect(result).to.be.true;\r\n expect(builder.geometries.length).to.be.equal(2);\r\n expect(builder.geometries[1] instanceof Path).to.be.true; // The second geometry should be the outline geometry, which is a Path\r\n });\r\n\r\n it(\"should set fill and border colors from frame\", () => {\r\n const builder = new MockBuilder();\r\n const frame: TextFrameStyleProps = {\r\n shape: \"rectangle\",\r\n fillColor: ColorDef.blue.toJSON(),\r\n borderColor: ColorDef.red.toJSON(),\r\n borderWeight: 3,\r\n };\r\n appendFrameToBuilder(builder, frame, defaultRange, defaultTransform, defaultParams);\r\n const params = builder.params[builder.params.length - 1];\r\n expect(params.fillColor?.tbgr).to.equal(ColorDef.blue.tbgr);\r\n expect(params.lineColor?.tbgr).to.equal(ColorDef.red.tbgr);\r\n expect(params.weight).to.equal(3);\r\n });\r\n\r\n });\r\n describe(\"computeGeometry\", () => {\r\n const shapes = textAnnotationFrameShapes.filter(shape => shape !== \"none\");\r\n it(\"should compute different frame shapes and they should be continuous\", () => {\r\n for (const shape of shapes) {\r\n const frame = computeFrame({ frame: shape, range: defaultRange, transform: defaultTransform });\r\n expect(frame).to.exist;\r\n\r\n const curvePrimitives = frame.collectCurvePrimitives(undefined, true);\r\n\r\n if (curvePrimitives.length > 1) {\r\n // The start point of a given segment should be the end point of the previous segment\r\n const isContinuousShape = isContinuous(frame.collectCurvePrimitives(undefined, true))\r\n expect(isContinuousShape, `Frame shape ${shape} should be continuous`).to.be.true;\r\n }\r\n }\r\n });\r\n\r\n it(\"should apply transform\", () => {\r\n const origin = Point3d.create(5, 6, 7);\r\n const vector = Vector3d.create(1, 2, 3);\r\n vector.tryNormalizeInPlace();\r\n const transform = Transform.createRigidFromOriginAndVector(origin, vector)!; // This transform is something I made up for this test. It should exist.\r\n\r\n for (const shape of shapes) {\r\n const rotatedFrame = computeFrame({ frame: shape, range: defaultRange, transform });\r\n const unRotatedFrame = computeFrame({ frame: shape, range: defaultRange, transform: defaultTransform });\r\n\r\n const control = unRotatedFrame.cloneTransformed(transform)!; // This transform is something I made up for this test. It should exist.\r\n expect(rotatedFrame.isAlmostEqual(control), `Rotated frame for shape ${shape} should match control`).to.be.true;\r\n }\r\n });\r\n });\r\n});\r\n"]}
|
|
@@ -73,6 +73,30 @@ describe("deleteElements (native bulk delete API)", () => {
|
|
|
73
73
|
for (const id of retained)
|
|
74
74
|
assertExists(id, `[${label}] ${id} should have been retained`);
|
|
75
75
|
txn.abandonChanges();
|
|
76
|
+
// Verify that the same test case produces the same result when using the deprecated iModelDb.elements.deleteElements API, to ensure that the deprecation does not cause any regressions.
|
|
77
|
+
executeTestCaseDeprecated(label, idsToDelete, deleted, retained, expectedFailed);
|
|
78
|
+
};
|
|
79
|
+
const executeTestCaseDeprecated = (label, idsToDelete, deleted, retained, expectedFailed = []) => {
|
|
80
|
+
const previousEnforcement = EditTxn.implicitWriteEnforcement;
|
|
81
|
+
EditTxn.implicitWriteEnforcement = "allow";
|
|
82
|
+
try {
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
84
|
+
const resultStatus = iModelDb.elements.deleteElements(idsToDelete);
|
|
85
|
+
if (expectedFailed.length === 0)
|
|
86
|
+
assert.equal(resultStatus.status, BulkDeleteElementsStatus.Success);
|
|
87
|
+
else
|
|
88
|
+
assert.equal(resultStatus.status, (expectedFailed.length === idsToDelete.length) ? BulkDeleteElementsStatus.DeletionFailed : BulkDeleteElementsStatus.PartialSuccess);
|
|
89
|
+
assert.sameMembers(Array.from(resultStatus.failedIds), expectedFailed, `[${label}] failed set mismatch`);
|
|
90
|
+
for (const id of deleted)
|
|
91
|
+
assertDeleted(id, `[${label}] ${id} should have been deleted`);
|
|
92
|
+
for (const id of retained)
|
|
93
|
+
assertExists(id, `[${label}] ${id} should have been retained`);
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
97
|
+
iModelDb.abandonChanges();
|
|
98
|
+
EditTxn.implicitWriteEnforcement = previousEnforcement;
|
|
99
|
+
}
|
|
76
100
|
};
|
|
77
101
|
/**
|
|
78
102
|
* Shared hierarchy used throughout the parent-child tests:
|
|
@@ -108,6 +132,27 @@ describe("deleteElements (native bulk delete API)", () => {
|
|
|
108
132
|
it("delete a root element", () => {
|
|
109
133
|
executeTestCase("root cascades", [parentA], [parentA, childA1, grandchildA1, childA2, grandchildA2, childA3], [parentB, childB1, childB2, standalone, childS1]);
|
|
110
134
|
});
|
|
135
|
+
it("Second call to deleteElement fails if a read cursor on a temp table is open", () => {
|
|
136
|
+
// Create a temp table on the same SQLite connection that the native bulk-delete will use to simulate a shared temp table lock
|
|
137
|
+
iModelDb.withSqliteStatement("CREATE TABLE IF NOT EXISTS temp.temp_table (x INTEGER)", (s) => s.step());
|
|
138
|
+
iModelDb.withSqliteStatement("INSERT INTO temp.temp_table VALUES (1)", (s) => s.step());
|
|
139
|
+
const lockStmt = iModelDb.prepareSqliteStatement("SELECT x FROM temp.temp_table");
|
|
140
|
+
assert.equal(lockStmt.step(), DbResult.BE_SQLITE_ROW);
|
|
141
|
+
const el1 = insertElement();
|
|
142
|
+
const el2 = insertElement();
|
|
143
|
+
const result1 = txn.deleteElements([el1]);
|
|
144
|
+
const result2 = txn.deleteElements([el2]);
|
|
145
|
+
for (const result of [result1, result2]) {
|
|
146
|
+
assert.equal(result.failedIds.size, 0);
|
|
147
|
+
assert.equal(result.status, BulkDeleteElementsStatus.Success, "deleteElements call must succeed");
|
|
148
|
+
assert.equal(result.sqlDeleteStatus, DbResult.BE_SQLITE_OK);
|
|
149
|
+
}
|
|
150
|
+
// Would have been the case if "DROP TABLE IF EXISTS..." was used (bug)
|
|
151
|
+
assert.notEqual(result2.status, BulkDeleteElementsStatus.DeletionFailed);
|
|
152
|
+
assert.notEqual(result2.sqlDeleteStatus, DbResult.BE_SQLITE_LOCKED);
|
|
153
|
+
lockStmt[Symbol.dispose](); // release the simulated read-lock
|
|
154
|
+
txn.abandonChanges();
|
|
155
|
+
});
|
|
111
156
|
it("explicitly delete the whole tree", () => {
|
|
112
157
|
executeTestCase("redundant descendants in input", [parentA, childA1, grandchildA1, childA2], [parentA, childA1, grandchildA1, childA2, grandchildA2, childA3], [parentB, childB1, childB2, standalone, childS1]);
|
|
113
158
|
});
|